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的构造方法
1 | 官方不建议直接使用Message()方式创建Message对象 推荐使用Message.obtain方法创建 |
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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的原因
1 2 3 4 | //私有构造方法 需要调用静态方法prepare()才能创建 类似单例模式<br>private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } |
1 2 3 4 5 6 7 | 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()内部阻塞
1 2 3 4 5 6 7 8 9 | public static void loop() { final Looper me = myLooper(); ...other //其他代码 for (;;) { if (!loopOnce(me, ident, thresholdOverride)) { return ; } } } |
1 2 3 4 5 6 7 8 9 | 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()方法里面
1 2 3 4 5 6 7 | <em id= "__mceDel" ><em id= "__mceDel" > public static void main(String[] args) {<em id= "__mceDel" > </em> //这里创建主线程的Looper Looper.prepareMainLooper();<br> //调用Looper.loop()执行死循环 Looper.loop(); throw new RuntimeException( "Main thread loop unexpectedly exited" ); } </em></em> |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)