要点5 消息机制和多线程

5. 消息机制和多线程的使用

UI线程的消息循环是在ActivityThread方法中创建的, 该函数为Android应用程序的入口.

在Android应用启动的时候, 会默认有一个主线程(UI线程), 这个线程会关联一个消息队列, 所有操作都会被封装成消息交给主线程来处理.

Looper总结:

  1. 通过Looper.prepare来创建looper对象(消息队列封装在Looper对象中), 并且保存在sThreadLocal中.
  2. 消息循环的建立通过Looper.loop()方法, loop方法实际上是建立一个死循环, 不断从消息队列中取出消息.

Handler将消息发送给消息队列, 消息队列又将消息分发给Handler来处理.

Message的两个重要成员变量
Hander target;
Runnable callback;

不管是post一个Runnable(包装成Message, callback设置为runnable成员变量)还是sendMessage, 都会调用sendMessageDelayed(msg, time)方法, Handler最终将消息追加到MessageQueue中, 而Looper不断取出从MessageQueue中读取消息, 并调用Handler的dispathMessage来处理消息.
dispathMessage方法是一个分发方法, 如果Runnable类型的callback变量不为空, 则callback.run中执行更新UI的代码, 否则会走到handMessage这个分支.

Handler构造方法中通过Looper.myLooper来获取Looper对象.

//1. 成员变量mLooper的获得
mLooper = Looper.myLooper();

//1. Looper.myLooper的源码
/**
  * Return the Looper object associated with the current thread.  Returns
  * null if the calling thread is not associated with a Looper.
  */
 public static @Nullable Looper myLooper() {
     return sThreadLocal.get();
}
安卓中多线程的实现

使用JavaSE中线程 和 线程池,
为了方便封装了一些常用的类AsyncTask, HandlerThread.

线程池的优点

  1. 重用存在的线程, 减少对象创建,销毁的开销
  2. 有效控制最大的并发线程数, 提高系统资源的使用率, 同时避免过多资源竞争, 避免堵塞
  3. 提供定时执行, 单线程, 并发数控制等功能

在android平台, 由于资源有限, 最常用的就是通过Executors.newFixedThreadPool(int size)来启动固定数量的线程池.

AsyncTask的原理

onPreExecute
doInBackground
onProgressUpdate
onPostExecute

概括来说, 我调用execute方法后, execute方法先调用onPreExecute方法,
然后由ThreadPoolExecutors实例sExecutor执行一个FutureTask任务, 这个过程中doInBackground将被调用, 如果在doInBackground中调用了publicProgress方法, 则通过sHandler发送一条MESSAGE_POST_PROGRESS消息, 更新进度;
如果遇到异常, 则发送一条MESSAGE_POST_CANCEL消息, sHandler处理消息时, onCancelled方法会被调用;
如果执行成功, 则发送一条MESSAGE_POST_RESULT的消息, sHandler处理消息时会调用onPostExectute(result)方法, 让用户得以在UI线程处理结果.
总的来说, AsyncTask的本质是使用线程池技术 和 Handler封装, 较少了处理问题的复杂度, 提高了开发效率.

HandlerThread

你可能感兴趣的:(要点5 消息机制和多线程)