资源描述
2013年1月19日0:40:31
第三章 事件处理
3.1android的事件处理
Android提供了两种方式的事件处理:
-》基于回调的事件处理
-》基于监听器的事件处理
对应android基于监听的事件处理而已,主要做法就是为android界面组件绑定特定的事件监听器
对于android基于回调的事件处理而已,主要做法就是写android组件特定的回调地方法,或者重写Activity的回调方法。Android为绝大部分组件都提供了事件响应的回调方法,开发者只要重写它们即可。
一般来说,基于回调的事件处理可用于处理一些具有通用性的事件,基于回调的事件处理代码会显得比较简洁但对于某些特定的事件,无法使用基于回调的事件处理,只能采用基于监听的事件处理。
3.2基于监听的事件处理
基于监听的事件处理是一种更“面向对象”的事件处理。
3.2.1事件监听的处理
在事件监听的处理模型中,主要涉及如下三类对象。
-》Event Source(事件源):事件发生的场所,通常就是各个组件,例如按钮、窗口、菜单
-》Event(事件):事件封装了界面组件上发生的特定事情(通常就是一次用户操作)。
如果程序需要获得界面组件上所发生事件的相关信息,一般通过Event对象来获取。
-》Event Listener(事件监听器):负责监听事件源所发生的事件。并对各种事件做出相应的响应。
实例:(3.2.1)
基于监听的事件处理模型的编程步骤如下:
-》获取普通界面组件(事件源),也就是被监听的对象
-》实现事件监听器类,该监听器类是一个特殊的Java类,必须实现一个XXXXListener接口
-》调用事件源的setXXXListener方法将事件监听器对象注册给普通组件(事件源)
上例的程序:可以发现基于监听的事件处理有如下规则。
-》事件源:就是程序中的按钮。应用程序中任何组件都可以作为事件源。
-》事件监听器:就是程序中的MyClickListener类。监听器必须由程序员负责实现,实现监听器类的关键就是实现处理器方法。
-》注册监听器:只要调用事件源的setXXXListener(XXXListener)方法即可。
2013年1月20日16:50:32
3.2.2事件和事件监听器
当外部动作在android组件上进行操作时,系统会自动生成事件对象,这个事件对象会作为参数传给注册到事件源上的事件监听器。
事件监听器的处理模型涉及三个成员:事件源、事件和事件监听器。其中事件源容易创建,任意界面组件都可以作为事件源;事件的产生无需程序员关心,他是由系统自动产生的,所以,实现事件监听器是整个事件处理的核心。
对于键盘事件、触摸屏事件等,程序需要获取事件发生的详细信息:例如键盘事件需要获取是哪个键触发的事件,触摸屏事件需要获取事件发生的位置等,对于这种包含更多信息的事件,android同样会将事件信息封装成XXXEvent对象,并把该对象作为参数传入事件处理器。
实例:控制飞机移动(3.2.2)
在基于事件监听的处理事件模型中,事件监听器必须实现事件监听器接口,android为不同的界面组件提供了不同的监听器接口,这些接口通常以内部类的形式存在。以View类为例,它包含了如下几个内部接口:
--》View.OnClickListener:单击事件的事件监听器必须实现的接口
-》View.OnCreateContextMenuListener:创建上下文菜单事件的事件监听器必须实现的接口
-》View.onFocusChangeListener:焦点改变事件的事件监听器必须实现的接口
-》View.onKeyListener:按键事件监听器必须实现的接口
-》View.onLongClickListener:长单击事件的事件监听器必须实现的接口
-》View.onTouchListener:触摸屏事件的事件监听器必须实现的接口
所谓事件监听器,其实就是实现了特定接口的Java类的实例。在程序中实现事件监听器,通常有如下几种形式:
-》内部类形式:将事件监听器类定义成当前类的内部类
-》外部类形式:将事件监听器类定义成一个外部类
-》Activity本身作为事件监听器类:让Activity本身实现监听器接口,并实现事件处理方法
-》匿名内部类形式:使用匿名内部类创建事件监听器对象
3.2.3内部类作为事件监听器
前面程序中所使用的事件监听器类都是内部类形式,使用内部类可以在当前类中复用该监听器类;因此监听器类是外部类,所以可以自由访问外部类的所以界面组件。这也是内部类的两个优势。
3.2.4外部类作为事件监听器类
使用顶级类定义事件监听器类的形式比较少见,主要因为如下两个原因:
-》事件监听器通常属于特定的GUI界面,定义成外部类不利于提高程序的内聚性。
-》外部类形式的事件监听器不能自由访问创建GUI界面的类中的组件,编程不够简洁
但如果某个事件监听器确实需要被多个GUI界面所共享,而且主要是完成某种业务逻辑的实现,则可以考虑使用外部类的形式来定义事件监听器类。
2013年1月21日13:51:22
实例:3.2.3
程序定义了一个外部类作为onLongClickListener类,该事件监听器实现了发送短信的功能
3.2.5Activity本身作为事件监听器
这种形式使用Activity本身作为监听器类,可以直接在Activity类中定义事件处理器方法,这种形式非常简洁。但这种做法有两个缺点:
-》这种形式可能造成程序结构混乱,Activity的主要职责应该是完成界面初始化工作,但此时还需要包含事件处理器方法,从而引起混乱
-》如果Activity界面类需要实现监听器接口,让人感觉比较怪异。
实例:3.2.4
3.2.6匿名内部类作为事件监听器类
大部分时候,事件处理器都没有什么复用价值,因此大部分事件监听器只是临时使用一次,所以使用匿名内部类形式的事件监听器更合适。实际上,这种形式是目前使用最广泛的事件监听器形式。
实例:3.2.5
3.2.7直接绑定到标签
Android还有一种更简单的绑定事件监听器的形式,直接在界面布局文件中作为指定标签绑定事件处理方法。
对于很多android标签而言,他们都支持如onClick、 onLongClick等属性,这种属性的属性值就是一个形如xxx(View source)的方法的方法名。
实例:3.2.6
3.3基于回调的事件处理
3.3.1回调机制与监听机制
如果说事件监听机制是一种委托式的事件处理,那么回调机制则恰好与之相反:基于回调的事件处理模式来说,事件源于事件监听器是统一的,或者说事件监听器完全消失了。当用户在GUI组件上激发某个事件时,组件自己特定的方法将会负责处理该事件。
为了使用回调机制类处理GUI组件上所发生的事件,我们需要为该组件提供对应的事件处理方法-而Java又是一种静态语言,我们无法为某个对象动态的添加方法,因此只能继承GUI组件类,并重写该类的事件处理方法来实现。
为了实现回调机制的事件处理,android为所有的GUI组件都提供了一些事件处理方法,以View为例,该类包含如下方法:
-》boolean onKeyDown(int keyCode,keyEvent event):当用户在该组件上按下某个按键时触发该方法。
-》boolean onKeyLongPress(int keyCode,KeyEvent event):当用户在该组件上长按某个按键时触发该方法。。
-》boolean onkeyShortcut(int keyCode,KeyEvent event):当一个键盘快捷键事件发生触发该方法
-》boolean onKeyUp(int keyCode,KeyEvent event):当用户在该组件上松开某个按键时触发该方法
-》boolean onTouchEvent(MotionEvent event):当用户在该组件上触发触摸屏事件时触发该方法。
-》boolean onTrackballEvent(MotionEvent event):当用户在该组件上触发轨迹球屏事件时触发该方法。
实例:3.3.1
3.3.2基于回调的事件传播
几乎所有基于回调的事件处理方法都有一个boolean类型的返回值,该返回值用于标识该处理方法是否能完全处理该事件。
-》如果处理事件的回调方法返回true,表明该处理方法已完全处理该事件,该事件不会传播去。
-》如果处理事件的回调方法返回false,表明该处理方法并未完全处理该事件,该事件会传播出去 。
对于基于回调的事件传播而已,某组件上所发生的事情不仅激发该组件是哪个的回调方法,也会触发该组件所在Activity的回调方法-只要事件能传播到该Activity。
实例:3.3.2(略)
3.3.3重写onTouchEvent方法响应触摸屏事件
对于android提供的两种事件处理模型,不难发现基于监听的事件处理模型具有更大的优势:
-》基于监听的事件模型分工更明确,事件源、事件监听由两个类分开实现,因此具有更好的可维护性。
-》android的事件处理机制保证基于监听的事件监听器会被优先触发。
但在某些特定情况下,基于回调的事件处理机制更好的提高程序的内聚性。
实例3.3.3(略)
2013年1月22日12:37:39
3.4响应系统设置的事件
在开发android应用时,有时候可能需要让应用程序随系统设置而进行调整,比如判断系统的屏幕方向、判断系统方向的方向导航设备等除此之外,有时候可能还需要让应用程序监听系统设置的更改,对系统设置的更改做出响应。
3.4.1Configuration类简介
Configuration类专门用于描述手机设备上的配置信息,这些配置信息既包含用户特定的配置项,也包括系统的动态设备配置。
程序可调用ACtivity的如下方法获取系统的Configuration对象:
Configuration cfg=getResource().getConfiguration();
一旦获得了系统Configuration对象,该对象提供了如下常用属性来获取系统的配置信息:
-》public float fontScale:获取当前用户设置的字体的缩放因子。
-》public int keyboard:获取当前设置所关联的键盘类型。该属性可能返回如下值:KEYBOARD_NOKEYS、KEYBOARD_QWERTY(普通电脑键盘)、KEYBOARD_12KEY(只有12个键的小键盘)。
-》public int keyboardHidden:该属性返回一个boolean值用于标识当前键盘是否可用。该属性不仅会判断系统的硬件键盘,也会判断系统的软键盘(位于屏幕上)。
如果该系统的硬件键盘不可用,但软键盘可用,该属性也会返回KEYBOARDHIDDEN_NO;只有当两个键盘都不可用时才返回KEYBOARDHIDDEN_YES。-
-》public Locale local:获取用户当前的Local。
-》public int mcc:获取移动信号的国家码。
-》public int mnc;获取移动信号的网络码。
-》public int navigation:判断系统上方向导航设备的类型。该属性可能返回如NAVIGATION_NONAV(无导航)、NAVIGATION_DPAD(DPAD导航)、NAVIGATION_TRACKBALL(轨迹球导航)、NAVIGATION_WHEEL(滚轮导航)等属性值。
-》public int orientation:获取系统屏幕的方向,该属性可能返回TOUCHSEREEN_NOTOUCH(无触摸屏)、TOUCHSCREEN_STYLUS(触摸笔式的触摸屏)、TOUCHSCREEN_FINGER(接受手指的触摸屏)。
实例:获取系统设备状态(3.4.1)
该程序只是提供了4个文本框来显示系统的屏幕方向、触摸屏方式等状态。
程序的Java代码主要可分为两步:
-》获取系统的Configuration对象
-》调用Configuration对象的属性来获取设备状态
3.4.2重写onConfigurationChanged响应系统设置更改
如果程序需要监听系统设置的更改,则可以考虑重写Activity的onConfigurationChanged(Configuration newConfig)方法,该方法是一个基于回调的事件处理方法,当系统设置发生更改时,该方法会被自动触发。
为了在程序中动态地更改系统设置,我们可调用Activity的setRequestedOrientation(int)方法来修改屏幕的方向。
系统设置的权限
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION"/>
还要添加:
<activity
android:name=".Test3_4_2"
android:label="@string/title_activity_test3_4_2"
android:configChanges="orientation" >
不然Toast不显示
3.5Handler消息传递机制
Android的消息传递机制是另一种形式的“事件处理”,这种机制主要是为了解决android应用的多线程问题-android平台不允许Activity新启动的线程访问该Activity里的界面组件,这样就会导致新启动的线程无法动态改变界面组件的属性值。但在实际android应用开发中,尤其是涉及动画的游戏开发中,需要让新启动的线程周期性地改变界面组件的属性值,这就需要借助于Handler的消息传递机制来实现了。
3.5.1Handler类简介
Handler类的主要作用有两个:
-》在新启动的线程中发送消息
-》在主线程中获取、处理消息
在新启动的线程中发送消息;然后在主线程中获取、并处理消息。
为了让主线程能“适时”地处理新启动的线程发送的消息,显然只能通过回调的方式来实现-开发者只要重写Handler类中处理消息的方法,当新启动的线程发送消息时,Handler类中处理消息的方法被自动回调。
Handler类包含如下方法用于发送、处理消息。
-》void handleMessage(Message msg):处理消息的方法,该方法通常用于重写。
-》final boolean hasMessage(int what):检查消息队列中是否包含what属性为指定值的消息。
-》final boolean hasMessage(int what,Object object):检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息。
-》多个重载的Message obtainMessage():获取消息。
-》sendEmptyMessage(int what):发送空消息。
-》final boolean sendEmptyMessageDelayed(int what,long delayMillis):指定多少毫秒之后发送空消息。
-》final boolean sendMessage(Message msg):立即发送消息。
-》final boolean sendEmptyMessageDelayed(Message msg,long delayMillis):指定多少毫秒之后发送消息。
3.5.2Handle使用案例
通过一个新线程来周期性地修改ImageView所显示的图片,通过这种方式来开发一个电话效果
展开阅读全文