目录介绍
1.关于handler消息机制图
2.关于handler基本介绍
3.使用handler的几种方法
4.关于handler底层源码解读
1.关于Handler消息机制图
2.关于Handler机制基本解读
Message
消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
sendMessage(message); //发送消息
sendEmptyMessage(0); //其实内部实现还是和上面一样
endEmptyMessageAtTime(int what, long uptimeMillis); //定时发送空消息
sendEmptyMessageDelayed(int what, long delayMillis); //延时发送空消息
sendMessageAtTime(Message msg, long uptimeMillis); //定时发送消息
sendMessageDelayed(Message msg, long delayMillis); //延时发送消息
sendMessageAtFrontOfQueue(Message msg); //最先处理消息(慎用)
Handler
处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue
消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
把消息进行排序,排序的依据就是消息要执行的时间
Looper
消息泵,不断地从MessageQueue中抽取Message执行。通过Looper去消息队列取消息
当主线程创建的时候,就会创建一个looper,looper在new的时候会创建一个MessageQueue 。所以,一个线程对应一个Looper一个Looper对应一个MessageQueue
Looper创建之后必须调用loop方法,loop方法中有一个死循环,这个死循环会不断去消息队列里取消息,取出消息之后就会调用handler的handlemessage方法处理消息
Thread
线程,负责调度整个消息循环,即消息循环的执行场所。
3.使用handler的几种方法
1.1主线程中定义Handler,子线程中发消息,通知Handler完成UI更新
Handler对象必须定义在主线程中,如果是多个类直接互相调用,就不是很方便,需要传递content对象或通过接口调用
在主线程中
方式1:使用 Handler.sendMessage()
主线程接收消息处理操作
private Handler myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case 0:
//更新UI等
break;
case 1:
//更新UI等
break;
default:
break;
}
}
};
//开启一个子线程,子线程发送信息
new Thread(
new Runnable() {
@Override
public void run() {
//处理耗时逻辑
if(a==1){ //直接发送信息,消息标识中并没有带参数
/**
*获取消息,尽量用obtainMessage()方法,查看源码发现,该方法节省内存。
*不提倡用Messenger msg=new Messenger()这种方法,每次创建一个对象,肯定不节省内存啦!
*至于为什么该方法还存在,估计还是有存在的必要吧。(留作以后深入研究)
*/
Message message = myHandler.obtainMessage();
message.what = 1; //消息标识
myHandler.sendMessage(message); //发送消息
}else if(a==2){
Message msg = myHandler.obtainMessage();
msg.what = 1; //消息标识
msg.arg1=2; //存放整形数据,如果携带数据简单,优先使用arg1和arg2,比Bundle节省内存。
msg.arg2=3; //存放整形数据
Bundle bundle=new Bundle();
bundle.putString("dd","abcd");
bundle.putInt("love",5);
msg.setData(bundle);
msg.obj=bundle; //用来存放Object类型的任意对象
myHandler.sendMessage(msg); //发送消息
}else if(a==3){
Message obtain = Message.obtain();
obtain.what = 1;
myHandler.sendMessage(obtain);
}else if(a==4){
myHandler.sendEmptyMessage(0); //其实内部实现还是和上面一样
}
}
}
).start();
方式2:使用Handler.post()
// 步骤1:在主线程中创建Handler实例
private Handler mhandler = new mHandler();
// 步骤2:在工作线程中 发送消息到消息队列中 & 指定操作UI内容
// 需传入1个Runnable对象
mHandler.post(new Runnable() {
@Override
public void run() {
... // 需执行的UI操作
}
});
// 步骤3:开启工作线程(同时启动了Handler)
// 多线程可采用AsyncTask、继承Thread类、实现Runnable
2.1用Activity对象的runOnUiThread方法更新
new Thread() {
public void run() {
//这儿是耗时操作,完成之后更新UI;
runOnUiThread(new Runnable(){
@Override
public void run() {
//更新UI
}
});
}
}.start();
如果在非上下文类中(Activity),可以通过传递上下文实现调用;
Activity activity = (Activity) imageView.getContext();
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
//更新UI
imageView.setImageBitmap(bitmap);
}
4.关于handler底层源码解读
见https://www.jianshu.com/p/b4d745c7ff7a
作者:潇湘剑雨_
链接:https://www.jianshu.com/p/2c5d87162987
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。