需要的类
- handler
- message
- messageQueue
存在意义
- 主线程不能做耗时操作,只能放在子线程
- 子线程不能修改主线程UI。
三者之间如何协作
浅显理解
- 线程A需要对线程B的界面需要操作时,会先将需要操作的数据封装成Message对象
- Message msg=handle.obtainMessage()
- Message对象通过B线程创建的Handler对象的sendMessage方法保存到B线程的Looper对象的成员变量MessageQueue中
-
- 主线程的Looer系统创建,子线程自己创建
- Looper.loop()不断轮询MessageQueue
- 当B线程的Loop的静态方法loop方法发现MessageQueue中的Message 对象后loop方法将其交给Handler对象的handleMessage方法处理
深入理解
- messageQueue
- 链表形式存储Message对象
- 创建Message对象handle.obtainMessage()b)实际是调用了Message.obtain(),将handler对象传递给Message对象的target成员变量,以便handler的loop()方法将Message传递给Handler的方法MessageQueue.
public static Message obtain(Handler handler){
Message msg=obtain(); // 无参数 c)具体实现
msg.target=handler;
return msg
}
c)Message.obtain()方法的
sPool !=null){ //判断消息池是否为空
message msg=sPool; //消息池是链表
sPool=msg.next; //链表头指针移动到下一位
m.next==null;
return msg;
}
return new Message();
2.Handler
a)一个线程创建handler对象的时候已经获取到该线程的 Looper,messageQueue,子线程在创建handler对象之前要先创建Loop
publicic Handler(){
mLooper=Looper.myLooper();
If(mLooper ==null){//抛异常}
mQueue=mLooper.mQueue;
}`
b)handler.sendMessage() 将message存放到MessageQueue中,按照执行时间与消息队列中的其他消息进行比对,将其插入MessageQueue适当的位置
3.Looper
a)Looper.prepare()
1.sThreadLocal(new Looper());//TheadLocal 线程单例 一个线程里只能创建一个Looper对象
b) new Looper()
public Looper(){
mMessageQueue=new MessageQueue();
}
c)主线程的Looper如何自动创建及运行
1.系统文件的ActivityThread.javad中的Main方法调用Looper中的perpareMainLooper()方法,perpareMainLooper调用Looper.perpare()方法
2.Main方法调用Looper的loop()方法不断轮询消息队列让主线程不会退出
d)Looper对象的loop()方法不断轮询消息队列当发现消息,调用创建该消息时(handle.obtainMessage)保存的handler对象的dispatchMessage,通过dispatchMessage调用未实现的方法handleMessage
public static void loop(){ //伪代码
for( ; ; ){ //死循环
((Handler)(sg.target)).dispathMessage(msg); //msg 轮询到的msg
}
}
注意
i.其他线程只要 要操作该线程UI就要给该线程创建Handler对象
ii.其他线程只要 要操作该线程UI就要给该线程创建Looper对象(主线程除外)
iii.Looper通过loop()方法不断轮询MessageQueue
iv.loop()方法将MessageQueue中Message拿出来交给Handler方法handleMessage
v.MessageQueue是Looper的成员变量
vi.Handler是线程间通讯的工具