Android异步消息处理机制学习笔记
(一)Handler
什么是Handler
- Android消息机制的上层接口,Handler通过发送和处理Message和Runnable对象来关联相对应线程的MessageQueeu.
- 可以让对应的Message和Runable在未来的某个时间点进行相应处理;
- 让自己想要处理的耗时操作放在子线程,让更新UI的操作放在主线程。
Handler的使用方法
- post(runnable):实际也是调用sendMessage
- sendMessage(message)
Handler机制原理
原理
- Looper通过loop方法轮询MessageQueue消息,把消息发送给Handler处理;
- MessageQueue消息队列,先进先出原则,创建Looper时MessageQueue已被创建并和Looper关联到一起;
- Message就是消息对象,存储在消息队列中;
- Handler发送消息和处理消息。要想发送消息必须有Looper(只能发送到与其相关联的MessageQueue),并且处理Looper发来的消息。
注意:
- ThreadLocal只限于set/get自己线程的信息,Looper保存在ThreadLocal中可以保证每个线程有自己的Looper。
- Looper是怎么获取的,通过ThreadLocal的get方法获取的;Looper什么时候创建存储的,也就是ThreadLocal什么时候调用了set方法呢?Looper.prepare调用时创建一个Looper对象并set在ThreadLocal中;
- Looper.loop创建一个死循环,不断去消息队列读取消息并进行消息分发;
- 每一个Handler要与主线程的消息队列关联上,所以不能在内部类创建Handler(在子线程只要主动调用Looper.prepare和Looper.loop方法也是可以使用的)。
Handler引起的内存泄漏以及解决办法
- 原因
- 内部类持有外部类的匿名引用,导致外部activity无法释放
- 解决方案
- 使用静态内部类的Handler;
- 在onDestroy中释放Handler;
- Handler内部持有外部类的弱引用。
(二)AsyncTask
什么是AsyncTask
- Android轻量级的异步类,它本质上就是封装了线程池和Handler的异步框架,因此可以方便的在线程间进行切换。。
- 只能做耗时比较短的工作。
Async的使用方法
3个参数
- 执行耗时任务的参数;
- 执行过程中主线程得到的数据;
- 执行结束返回的数据。
5个方法
- onPreExecute在主线程调用,耗时操作前做一些初始化工作;
- doInBackground比较重要的,做耗时操作,并将结果返回到onPostExecute方法中;
- onPostExecute异步线程执行完时回调;
- publishProgress()在doInBackground中调用,也就是onProgressUpdate的调用间隔;
- onProgressUpdate异步线程执行时,在主线程提供出进度。
机制原理
- AsyncTask的本质是一个静态的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务都是提交到静态的线程池中执行;
- 线程池中的工作线程执行doInBackground(mParams)方法执行异步任务;
- 当任务状态改变之后,工作线程会向UI线程发送消息,AsyncTask内部的InternalHandler相应这些消息,并调用相关的回调函数。
注意事项
-
内存泄漏:非静态的内部类持有Activity的引用
- 静态内部类;
- 弱引用;
- 在onDestroy()中cancle.
生命周期:activity被销毁时并不会主动销毁AsyncTask,需要自己调用cancle方法。
- 结果丢失:屏幕旋转,内存低被回收等导致AsyncTask持有的界面被重新创建,AsyncTask引用是旧的,导致界面更新失败。
- 并行or串行:在Android1.6之前串行,任务放在线程池顺序执行,在1.6-2.3并行,2.3之后为了系统稳定改成串行,但是也可以执行并行,需要调用executeOnExecutor即可,不建议使用并行,不稳定。
(三)HandlerThread
HandlerThread是什么
产生背景
- 频繁的开启和销毁Thread子线程执行任务方便但耗费系统资源。
定义
- 本质就是一个Thread线程类,它继承了Thread
- 有自己的内部looper对象,可以进行Looper循环
- 通过获取HandlerThread的Looper对象传递给Handler对象,可以在handleMessage方法中执行异步任务;
- 优点是不会有阻塞,减少了对性能的消耗;
- 缺点是需要等待,不能同时进行多任务处理,处理效率较低;
- 与线程池和并发不同,HandlerThread是一个串行队列,HandlerThread背后只有一个线程。
HandlerThread源码解析
鸿洋大神的分析
(四)IntentService
IntentService是什么
-
简介
- IntentService是继承Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统的Service一样,同时,当任务执行完成后,IntentService会自动停止,而不需要我们手动或者调用stopSelf().另外,可以多次启动IntentService,但只有一个IntentService实例,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,直到最后一个执行完后自动销毁。
-
IntentService是什么
- 它本质是一种特殊的Service,继承自Service并且本身就是一个抽象类;
- 它内部通过HandleThread和Handler实现异步操作。
IntentService使用
- 创建IntentService时只需要实现onHandleIntent和构造方法,onHandleIntent为异步方法,可以执行耗时操作。