1 android事件处理概述
不论是桌面应用还是手机应用程序,面对最多的就是用户,经常需要处理用户的动作-------也就是需要为用户动作提供响应,这种为用户动作提供响应的机制就是事件处理。android提供了两套事件处理机制:
- 基于监听的事件处理
主要做法就是为Android界面组件绑定特定的事件监听器;android还允许在界面布局文件中为UI组件的android:onClick属性指定事件监听方法,该方式需要开发者在activity中定义该事件监听方法(该方法必须带有一个View类型的形参,该形参代表被单击的UI组件,当用户单击该组件时,系统将会激发android:onClick属性所指定的方法)
- 基于回调的事件处理
主要做法是重写android组件特定的回调方法,或者重写Activity的回调方法。(基于回调的事件处理可以用于处理一些具有通用性的事件(业务逻辑比较固定),某些特定事件处理,仍需事件监听机制。)
2 基于监听的事件处理
2.1 监听的处理模型
2.1.1 事件监听的处理模型中,主要涉及如下三类对象
- Event Source(事件源):事件发生场所,通常是指各个组件,如按钮、窗口、菜单等
- Event(事件):事件封装了界面组件上发生的特定事情,Event包含所发生事件的相关信息
- Event Listener(事件监听器):负责监听事件源所相关事件的发生,并对并对发生事件作出反应
2.1.2 事件处理流程图
2.1.3 基于监听的时间处理模型的编程步骤
- 获取普通界面组件的对象(事件源),即被监听对象
- 实现事件监听器类,该监听器类是一个特殊的java类,必须实现一个xxxListener接口
- 调用事件源的setXxxListener方法将监听对象注册给事件源
2.2 内部类作为事件监听器类
- 可以在当前父类中复用该监听器
- 可自由访问外部类的所有界面组件
2.3 外部类作为事件监听器类
2.3.1 该形式比较少见,主要有两点原因:
- 事件监听器对应于具体的组件,定义成外部类,不利于提高程序的内聚性
- 外部类不能够自由访问创建GUI界面类的组件,编程不够简洁
2.3.2 若某个监听器需要被多个GUI界面组件所共享,且主要是完成某种业务逻辑的实现,则可考虑外部类的形式
2.4 Activity本身作为监听器
直接用Activity本身作为监听器类,这种形式非常简洁,但这种做法有两个缺陷:
- 这种程序结构可能造成混乱,Activity的主要职责应该是完成界面初始化工作
- Activity类本身还要实现监听接口,显得结构臃肿
2.5 匿名内部类作为事件监听器
- 由于大部分时候事件处理器都没有什么复用价值,因此大部分都是一次性使用,故造成此方法为最常用方法
2.6 直接绑定到标签
- 该方法结构简洁
- 但是结构也相对比较固定,适用范围有限(只支持onClick)
3 基于回调的事件处理
3.1 回调机制与监听机制
- 事件监听机制是一种委托式的事件处理,事件源和事件监听器分离,事件源发生器特定的事件后,该事件交给事件监听器负责处理
- 基于回调的事件模型来说,事件源与事件监听器是统一的,事件发生后,还是又事件源本身负责处理
- 为了使组件自身处理事件,则必须为组件对象添加方法,方法无法动态添加,故预置处理接口,继承重写方法即可
3.2 android为所有GUI组件都提供了一些事件处理的回调方法,以View为例,该类包含以下方法:
- onKeyDown,当用户在该组件上按下某个按键时触发该方法
- onKeyLongPress,当用户在组件上长按某个按键时触发该方法
- onKeyShortcut,当一个键盘快捷事件发生时触发该方法
- onKeyUp,当用户在该组件上松开某个按钮时触发该方法
- onTouchEvent ,当用户在该组件上触发触摸屏事件时触发该方法
- onTrackballEvent,当用户在该组件上触发轨迹球屏事件时触发该方法
3.3 基于回调的事件传播
几乎基于回调的事件处理方法都有一个boolean类型的返回值,该返回值用于标识该处理方法是否能完全处理该事件:
- 如果处理事件的回调方法返回true,表明该处理方法已经完全处理该事件,该事件不会传播出去
- 如果处理时间的回调方法返回false,则表明处理方法并未完全处理事件,该事件会传播出去,
- 事件触发顺序为:事件源监听处理器---->事件源本身回调函数----->事件源父组件(递归而上)
3.4 两种处理模型的区别
- 基于监听的事件模型分工更明确,事件源、事件监听分别有两个类分开实现,因此具有更好的可维护性
- Android的事件处理机制保证基于监听的事件监听器会被优先触发
3.5 示例
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal"> <EditText android:id="@+id/address" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="请填写收信号码" /> <EditText android:id="@+id/content" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="请填写短信内容" android:lines="3" /> <com.example.penghuster.myfirstapp.MyButton android:id="@+id/send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="发送" /> </LinearLayout>