参考:http://www.jianshu.com/p/02962454adf7
作为消息队列,它内部存储了一组消息,并队列的形式对外提供插入和删除的工作。单其内部并不是真正的队列,而是以单链表结构来存储。
在线程中调用Looper.prepare()...Looper.loop()就会把当前线程变成Looper线程(可以先简单理解:无限循环不退出的线程)。Looper线程不断等其他线程给它发消息,一有消息就根据消息做相应的处理,Looper的另外一部分工作就是在循环代码中会不断从消息队列挨个拿出消息给主线程处理。
主线程本身就是一个looper线程,他需要接收包括Activity启动,生命周期,更新UI,控件事件等一系列消息。
在同一进程中线程和线程之间资源是共享的,也就是对于任何变量在任何线程都是可以访问和修改的,只要考虑并发性做好同步就行了,因此,我们可以用handler和其他线程进行数据间的交互。
这里只要拿到MessageQueue 的实例,就可以往线程的MessageQueue放入消息,这里我们可以这么拿: mLooper = Looper.myLooper();mQueue = mLooper.mQueue; 但是Google 为了统一添加消息和消息的回调处理,又专门构建了Handler类. 这样一个Handler发出消息又确保消息处理也是自己来做. 具体做法就是在队列里面的Message持有Handler的引用(哪个handler 把它放到队列里,message就持有了这个handler的引用),然后等到线程轮询到这个message的时候,就来回调我们经常重写的Handler的handleMessage(Message msg)方法
每个Handler对象都会绑定一个Looper对象,每个Looper对象对应一个消息队列(MessageQueue)。如果在创建Handler时不指定与其绑定的Looper对象,系统默认会将当前线程的Looper绑定到该Handler上。
Handler只有一个消息队列,即MessageQueue。无论是通过post()传进去的线程对象还是sendMessage传入消息对象都将会被封装成消息对象后传入MessageQueue。Post实际上并不会单独开启一个新线程,而仍然在当前Looper绑定的线程中执行,Handler只是调用了该线程对象的run()而已。
子线程中使用looper:
在子线程中不能进行UI操作,因为UI是线程不安全的。为了保证的顺畅,不加锁,让耗时操作在线程执行,为此可以通过handler来完成。
这是消息传递的大概流程,Thread1为调用handler的线程。Thread2为与handler绑定的Looper的线程。
它是一个线程内部的数据存储类,用来存储指定线程的数据,也只有指定线程可以获取存储的数据。
ThreadLocal使用条件:
l 以线程为作用域并在不同线程有不同的数据副本
l 复杂逻辑下的对象传递(即函数调用栈比较深)
eg:
三个线程使用同一个ThreadLocal对象进行操作,但是每个线程有自己对应的一个副本。
它的内部采用key-value模式存储着对应线程的数据。
MessageQueue内部采用一个单链表的数据结构来维护消息队列,因为单链表在插入和删除上有很大优势。
这里消息队列的插入和读取分别对用着equeueMessage和next。
equeueMessage方法内部遍历链表,并将将新来的message加入到队列链表中
next方法内部也是通过遍历链表,将顶部对象传出,若消息队列中没有消息,那么next方法将会一直堵塞下去
通过Looper可将线程设置为looper线程:即内部有消息队列的线程。同时,Looper提供了一个getMainLooper方法,通过它可以在任何地方获取主线程的Looper。
这里在Looper对象中,持有单独的主线程sMainLooper。为了节省内存,Looper持有一个static的ThreadLocal,用它来存储之后Looper线程的数据。
Handler主要包含消息的发送和接收过程。
在handler中持绑定looper线程的Looper,通过looper可以获得MessageQueue。在looper.prepare()中完成。
发送消息时:调用send方法,将message对象放入messageQueue中,即使是post方法,最终也是调用send方法。
处理消息:调用dispatchMessage(Message msg)。在其中判断msg.callBack是否为null(即post方法放入的Runnable就是此时的callBack),不为则直接调用run方法。判断完msg.callBack之后,判断handler自己的handleMessage()。
注意:Runnable方法中run()/start()。run在原线程运行。Start则重新开一个线程。
主线程的handler就是ActivityThread.H。