【安卓开发艺术探索】第10章 消息机制Handler 笔记
来源:互联网 发布:直播免费刷人气软件 编辑:程序博客网 时间:2024/05/16 16:56
这一章主要讲Handler、Looper、MessageQueue这几者之间工作的机制,其实对于上层开发者,Handler用起来容易,但其背后的机制、尤其是Looper的机制却比较复杂,对某些部分,我暂时只能从一定程度上理解。
ThreadLocal
对于每一个线程,需要独立拥有一个Looper来进行消息管理。这个时候就需要派上ThreadLocal了。
ThreadLocal适合去维护一些以线程为作用域、不同线程使用的是不同的拷贝这种情景。
参考如下链接:http://blog.csdn.net/lufeng20/article/details/24314381 讲得比较清楚。
其实现是依赖Thread类中有如下定义:ThreadLocal.ThreadLocalMap threadLocals = null;
也就是每一个Thread对象都有一个threadLocals变量,类型是ThreadLocalMap,而这个类中有如下定义:private Entry[] table;
,这个Entry就是用来存放每一个ThreadLocal对象的容器。
static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } }
所以容易理解了,ThreadLocal存储过程就是以ThreadLocal自身的对象为key,泛型Object作为value,保存到ThreadLocalMap里的table数组中。而每个Thread都会拥有各自的ThreadLocalMap。
Looper+MessageQueue原理
调用Looper.prepare,来在一个新的线程中做初始化准备,这里面包括了构造一个新的Looper,保存当前的线程,构造新的MessageQueue。
调用Looper.loop,开始进入循环来等待接收消息。其主要是通过调用messageQueue的next()来等待新消息,再取出message,调用message.target.dispatchMessage(message)来处理此消息。message的target是Handler。这样即可完成消息的传递了。
似乎一切顺理成章,但有没有想过为何子线程中调用了loop后,进入了死循环但仍然不影响线程后面代码的执行?贴上两个链接:
- https://www.zhihu.com/question/34652589
- http://blog.csdn.net/ashqal/article/details/32107099
下面贴上我的一些测试,用以帮助理解,先说结论:Looper.loop方法是会阻塞运行的,即loop方法后面的代码在looper调用quit之前是不会执行的。见下面测试:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final Thread1 t1=new Thread1(); t1.start(); Thread t2 = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Message message = new Message(); message.setTarget(t1.handler); message.what=10; t1.handler.sendMessage(message); } },"thread2"); t2.start(); } class Thread1 extends Thread{ int i=0; Handler handler; @Override public void run() { Looper.prepare(); handler = new Handler(Looper.myLooper()) { @Override public void handleMessage(Message msg) { System.out.println("ssssssssss==================="+i); Looper.myLooper().quit(); } }; i=5; Looper.loop(); i=100;// System.out.println("ssssssssss==================="+i); } }}
执行结果如下:
04-16 20:33:44.368 4852-4885/com.zerastudio.test0416 I/System.out: ssssssssss===================5
去掉最后一行的注释后,执行结果:
04-16 20:34:58.651 6289-6321/com.zerastudio.test0416 I/System.out: ssssssssss===================504-16 20:34:58.651 6289-6321/com.zerastudio.test0416 I/System.out: ssssssssss===================100
足以说明了Looper调用了loop后会阻塞执行的,只有在调用了quit后才会继续往后执行。稍后会对ActivityThread进行研究,而Activity的各个生命周期均是从Looper的loop方法中开始被调用的。
Handler原理
在子线程中,通过目标线程的handler.obtainMessage,得到一个以目标线程handler作为target的message后,设置message信息,再用handler.send发送,也就是调用handler持有的messageQueue(来自Looper)的enqueueMessage插入到队列里,结合上面说的机制,唤醒loop,又转到了目标线程Handler的dispatchMessage方法里,于是切换了线程,就可以完成指定的动作了。
Message.obtain和new Message区别
Message维护了一个全局的messagePool,默认大小好像是50,回收利用对内存的消耗更小也更快。
- 【安卓开发艺术探索】第10章 消息机制Handler 笔记
- Android开发艺术探索读书笔记(第10章 消息机制)
- 【读书笔记】【Android开发艺术探索】第10章 Android 的消息机制
- 读书笔记:Android开发艺术探索之第10章 android的消息机制
- 【安卓开发艺术探索】第11章 线程线程池 笔记
- 【安卓开发艺术探索】第15章 性能优化、内存泄漏 笔记
- 【安卓开发艺术探索】第2章 进程线程通信与同步 笔记
- 【安卓开发艺术探索】第4章 View的测量、布局、绘制 笔记
- 【安卓开发艺术探索】第3章 触摸事件传递 笔记
- 安卓开发艺术探索笔记知识点
- 安卓开发艺术探索 笔记1
- 安卓开发艺术探索笔记第一章
- 《Android开发艺术探索》笔记(2)Android消息机制
- 《android开发艺术探索笔记》Part10、Android的消息机制
- 《安卓笔记》Handler消息机制
- 《Android 开发艺术与探索》笔记——(10)Android 的消息机制
- 安卓开发艺术探索
- 《Android开发艺术探索》读书笔记——Handler消息机制(ThreadLocal)
- eclipse中护眼色设置
- 2017年腾讯实习生校招面试感想
- 求斐波那契(Fibonacci)数列通项的七种实现方法
- android的缓存策略
- Python写入中文到mysql时乱码
- 【安卓开发艺术探索】第10章 消息机制Handler 笔记
- GPU加速
- LeetCode (5)Longest Palindromic Substring
- 并查集和最小生成树的总结
- 数据结构学习:单向链表的模板类实现
- Easy 6 Merge Two Sorted Lists(21)
- bootstrap的less源码学习之button组件控制
- Grunt教程-前端自动化
- HTML中data的属性