Android 学习随笔 Handler
Handler源码的几个核心类
Handler、Message、Looper、MessageQueue
Handler发送到收到回调的完整流程
Handler
1:Handler的构造函数
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) { mLooper = looper;//持有当前线程的Looper mQueue = looper.mQueue;//持有当前线程的Looper内的MessageQueue mCallback = callback;//接口回调 mAsynchronous = async;//是否同步 }
2:Handler过时默认函数 空参数构造方法会调用Looper.myLooper()获取当前线程的Looper
3:Handler会持有当前线程的Looper以及Looper里面的MessageQueue还有回调接口实现对象
Message
1、Message的构造方法
官方不建议直接使用Message()方式创建Message对象 推荐使用Message.obtain方法创建
public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } return new Message(); }
1.1 关于Message的sPool Message包含有一个Message属性next 所以Message是一个链表 sPool会进行一个Message对象回收工作 在recycleUnchecked()方法里面进行回收
1.2 Message的回收创建模式采用享元模式
1.3 Message的一个一个属性 Handler target 会保存当前发送Message的Handler对象 方便looper取出数据将相应的message发送给对应的Handler的Callback
MessageQueue
1 MessageQueue是一个单向链表
2 MessageQueue内部的next方法内部会调用一个native的方法 nativePollOnce(ptr, nextPollTimeoutMillis); MessageQueue没有数据就会在这里被阻塞
Looper
1 Looper的构造方法 及为什么一个线程只有一个Looper的原因
//私有构造方法 需要调用静态方法prepare()才能创建 类似单例模式
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
private static void prepare(boolean quitAllowed) { //用ThreadLocal来保存当前Looper 和抛异常的方式达到当前线程只有一个Looper的目的 if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
2 Looper重要函数loop() 以及loopOnce() loop内死循环调用loopOnce()方法轮询MessageQueue内的数据 如果MessageQueue没有数据就会被MessageQueue的next()内部阻塞
public static void loop() { final Looper me = myLooper(); ...other//其他代码 for (;;) { if (!loopOnce(me, ident, thresholdOverride)) { return; } } }
private static boolean loopOnce(final Looper me, final long ident, final int thresholdOverride) { ...//other msg.target.dispatchMessage(msg); ...other// return true; }
主线程(ActivithThread)中Looper的创建
1.ActivityThread的main()方法里面
public static void main(String[] args) { //这里创建主线程的Looper Looper.prepareMainLooper();
//调用Looper.loop()执行死循环 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }