Handler学习小结
Handler的消息传递机制
Handler白话理解:Handler是一个消息传递的机制,用来将子线程的数据传递给主线程。
高级用法:实现任意两个线程的数据传递。
1.Handler的引入
Handler类:让新启动的线程周期性地修改UI组件的属性值
常规使用的方式
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg){
super.handleMessage(msg);
switch (msg.what) {
case MESSAGE_WHAT:
Log.d(TAG,"main thread receiver message :" + ((String) msg.obj));
break;
}
}
}
private void sendMessageToMainThreadByWorkThread(){
new Thread(){
@Override
public void run(){
Message message = mHandler.obtainMessage(MESSAGE_WHAT);
message.obj = "I am message from work thread";
mHandler.sendMessage(message);
}
}.start();
}
白话总结:
1.先创建一个Handler(在主线程里)
2.重写Handler里面的handlerMessage方法,方法传入一个参数Message,其他线程传过来的信息就是这个。
3.子线程是怎么传递信息的呢,先通过.obtainMessage方法,获取一个Message的实例
补充:
Message.what => 用来标识信息的int值,通过该值主线程能判断出来自不同地方的信息来源。
Message.arg1/Message.arg2 => Message初始定义的用来传递int类型的两个变量。
Message.obj => 用来传递任何实例化对象。
sendMessage将Message发送出去。
两个子线程之间的通信
在一个线程创建Handler,另外一个线程通过持有该Handler的引用调用sendMessage发送消息。
private Handler handler;
private void handlerDemoByTwoWorkThread(){
Thread hanMeiMeiThread = new Thread(){
@Override
public void run(){
// Looper.prepare();
handler = new Handler(){
@Override
public void handleMessage(Message msg){
Log.d(TAG,"hanMeiMei receiver message:" + ((String) msg.obj));
Toast.makeText(MainActivity.this,((String) msg.obj),Toast.LENGTH_SHORT).show();
}
};
//Looper.loop();
}
};
Thread liLeiThread = new Thread(){
@Override
public void run() {
try{
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
Message message = handler.obtainMessage();
message.obj = "Hi MeiMei";
handler.sendMessage(message);
}
};
hanMeiMeiThread.setName("韩梅梅 Thread");
hanMeiMeiThread.start();
liLeiThread.setName("李雷 Thread");
liLeiThread.start();
}
2.Handler的执行流程
引入—Handler、Looper、Message这三者与异步消息处理线程
知识点一:异步消息处理线程启动后会进入一个无限的循环体中,每循环依次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环。若消息队列为空,线程则会阻塞等待。
知识点二:那么Android消息机制主要是指Handler的运行机制,Handler运行需要底层的MessageQueue和Looper支撑,其中MessageQueue采用的是单链表的结构,Looper可以叫做消息循环。由于MessageQueue只是一个消息存储单元,不能去处理消息,而Looper就是专门处理消息的,Loopr会以无限循环的形式去查找是否有新消息,如果有的话,就处理,否则就一直等待着。
知识点三:我们知道,Handler创建的时候会采用当前线程的Looper来构造消息循环系统,需要注意的是,线程默认是没有Looper的,如果需要使用Handler就必须为线程创建Looper,因为默认的UI主线程,也就是ActivityThread,ActivityThread被创建的时候就会初始化Looper,这也是在主线程中默认可以使用Handler的原因。
解析:
⭐️Message:Handler接收和处理的消息对象
1.2个整型数值:轻量级存储int类型的数据。
2.1个Object:任意对象。
3.reply To:线程通信时使用。
4.what:用户自定义的消息码,让接收者识别消息。
⭐️MessageQueue:Message的队列
1.采用先进先出的方式管理Message。
2.每个线程最多可以拥有一个。
⭐️Looper:消息泵,是MessageQueue的管理者,会不断从MessageQueue中取出消息,并将消息分给对应的Handler处理
1.每个线程只有一个Looper。
2.Looper.prepare():为当前线程创建Looper对象
3.Looper.myLooper():可以获得当前线程的Looper对象。
4.Handler:能把消息发送给MessageQueue,并负责处理Looper分给它的消息。
3.Handler的相关方法
????void handleMessage(Message msg):处理消息的方法。该方法通常用于被重写。
????final boolean hasMessages(int what):检查消息队列中是否包含what属性为指定值的消息。
????finalboolean hasMessages(int what,Object object):检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息
????多个重载的Message obtainMessage():获取消息
????sendEmptyMessage(int what):发送空消息
????final boolean sendEmptyMessageDelayed(int what,long delayMillis):指定多少毫秒后发送空消息
????final boolean sendMessage(Message msg):立即发送消息
????final boolean sendMessageDelayed(Message msg,long delayMillis):指定多少毫秒后发送消息
4.Handler的使用
如果写在主线程不需要Looper对象
Handler写在子线程中,则需自己创建一个Looper对象
总结:
1.在使用handler的时候,在handler所创建的线程需要维护一个唯一的Looper对象,每个线程对应一个Looper,每个线程的Looper通过ThreadLocal来保证,Looper对象的内部又维护有唯一的一个MessageQueue,所以一个线程可以有多个handler,但是只能有一个Looper和一个MessageQueue。
2.Message在MessageqQueue不是通过一个列表来存储的,而是将传入的Message存入到了上一个Message的next中,在取出的时候通过顶部的Message就能按放入的顺序依次取出Message。
3.Looper对象通过loop()方法开启了一个死循环,不断地从looper内的MessageQueue中取出Message,然后通过handler将消息分发传回handler所在的线程。
本文部分内容参考: