事件处理机制
- 基于监听的事件处理
做法:为Android界面组件绑定特定的时间监听器。 - 基于回调的事件处理
做法:重写Android组件特定的回调方法,或重写Android的回调方法。
事件三要素
- Event Source:事件源,事件发生的场所,通常就是各个组件
- Event:时间,事件封装了界面组件上发生的特定事情
- Event Listener:事件监听器,监听事件,并作出响应
实现事件监听器
- 内部类:将事件监听器定义成当前类的内部类
- 外部类:将事件监听器定义成一个外部类
- Activity本身作为事件监听器类
- 匿名内部类:最常用,原因:大部分事件监听器只是临时使用一次
- 直接绑定到组件标签XML
Handler消息传递机制
Android:只允许UI线程修改Activity里的UI组件。但在实际开发中,尤其是涉及动画的游戏开发中,需要让新启动的线程周期性地改变界面组件的属性值,这就需要借助于Handler的消息传递机制来实现。
Handler作用
- 在新启动的线程中发送消息
在主线程中获取、处理消息
为了让主线程能“适时”地处理新启动的线程所发送的消息,只能通过回调的方式来实现——开发者只要重写Handler类中的处理消息的方法,当新启动的线程发送消息时,消息会发送到与之关联的MessageQueue,而Handler会不断地从MessageQueue中获取并处理消息——这将导致Handler类中处理消息的方法被回调。
Handler、Loop、MessageQueue的工作原理
- Message:Handler接收和处理的消息对象
- Looper
每个线程只能拥有一个Looper。它的loop方法负责读取MessageQueue中的消息,读到消息之后就把信息之后就把消息交给发送该消息的Handler进行处理。 - MessageQueue
消息队列,采用先进先出的方式来管理Message - Handler
作用:发送消息和处理消息。程序使用Handler发送消息,被Handler发送的消息必须被送到指定的MessageQueue。也就是说,如果希望Handler正常工作,必须在当前线程中有一个MessageQueue,否则消息就没有MessageQueue进行保存了。不过,MessageQueue是由LoopER负责管理的,也就是说,如果希望Handler正常工作,必须在当前线程中有一个Looper对象。为了保证当前线程中有Looper对象,可分为如下两种情况处理:
- 主UI线程中,系统已经初始化了一个LoopER对象,因此程序直接创建Handler即可,然后就可通过Handler来发送消息,处理消息。
- 自己启动的子线程,必须自己创建一个Looper对象,并启动它。创建Looper对象调用它的prepare()方法即可。
尽量避免在UI线程中执行耗时的操作,通常采用启用新的线程来执行耗时任务,否则极大可能会导致ANR异常。
Async Task 异步任务
Android的UI组件主要负责处理用户的按键事件、触屏事件、屏幕绘图事件等,因此开发者的其他操作不应该、也不能阻塞UI线程,否则UI界面将会变得停止响应,超过20S将会引发Application Not Responding (ANR),必须牢记:不要在UI线程中执行一些耗时的任务。
为了解决新线程不能根性UI组件的问题,Android提供的解决方案:
1. 使用Handler实现线程之间的通信
2. Activity.runOnUiThread(Runnable)
3. View.post(Runnable)
4. View.postDelayed(Runnable, long)
以上方案出Handler外都略显繁琐。AsyncTask是一个轻量级的解决方案,适合用于简单的异步处理,不需要借助线程和Handler即可实现。
Steps
- 创建AsyncTask子类
- 实现如下方法
- doInBackground: 后台线程将要完成的任务;该方法可以调用publishProgress方法更新任务的执行进度;
- onProgressUpdate:在doInBackground方法中调用publishProgress更新任务的执行进度后,将会被触发;
- onPreExcute:在执行后台耗时操作前被调用。通常用于完成一些初始化的准备工作,比如在界面上显示进度条等;
- onPostExcute:当doInBackground完成后,系统自动调用该方法,并将doInBackground方法的返回值传给该方法。
- 调用AsyncTask子类实例的execute方法执行耗时任务
使用时必须遵守的规则
- 必须在UI线程中创建AsyncTask的实例
- 必须在UI线程中调用AsyncTask的execute方法
- AsyncTask的onPreExcute, onPostExcute, doInBackground, onProgressUpdate方法,不应爱由程序员调用,而由Android系统负责调用
- 每个AsyncTask只能被执行一次,多次调用将会引发异常