1、handler是什么?
它是android给我们提供用来更新UI的机制,也是一套消息处理机制,我们可以发送消息,也可以处理消息。
拓展:
看ForamWork层源码可以知道
Activity 里的生命周期方法回掉,也是通过handler发送消息,然后通过不同的msg做不同的分支处理。
ActivityThread是应用程序的核心的类,整个应用程序都是通过它创造,包括Activity,以及各种生命周期方法的回调。
里面会有一个默认创建main线程, 所有更新UI的线程都是根据这个main线程创建的
ActivityThread 就是通过Handler机制接受到AMS发送的Activity生命周期的执行管理, 然后进行相关操作
2、为什么要用handler?
正常来说,是不应该再主线程中进行网络请求和UI操作的,这些操作往往耗费大量时间,也会造成主线程的阻塞。
还有可能会造成界面错乱、性能下降等
所以Android设计的时候,就封装了一套消息创建、传递、处理机制,如果不遵循这样的机制就没有办法更新UI,
就会抛出异常信息。也就是不能在非UI线程进行更新UI
3、Handler怎么用?以及与Looper和Messagequeue的关系
先知道一点,1个线程中只能对应1个Looper实例,并且每一个主线程有一个threadLocal对象,它是用来关联Looper对象的。
handler机制如果想运行起来,必须的有Looper对象和messagequeue对象,那为什么在主线程new hanlder()会运行此机制,
点击ActivityThread源码的main方法里,系统会调用Looper.prepareMainLooper();去帮我们创建Looper对象,并且把这个
Looper对象保存到了threadLocal中,并且在Looper的构造方法里创建了Messagequeue对象。然后也会调用Looper.loop();
让这套机制开始工作,如果没有消息就阻塞,如果有的话,从消息队列里取消息,处理消息。这个方法一旦开启之后,
则会自动进入消息循环,这是一个隐式操作。
再点击handler构造方法可以知道,里面会执行Looper.myLooper(); 在点击进去看到这个方法会执行 threadLocal.get()方法
取出之前在threadLocal储存的Looper变量,然后获取到Looper对象,然后通过Looper对象调用它的成员变量mQueue可获取
到Messagequeue对象,这样它们三者就建立了关联。这样就可以运行hanlder消息处理机制了。
如果是在子线程:
子线程中是不会默认没有创建Looper对象,如果想让一个handler在一个子线程中生效,并且执行它的机制,就必须有Looper对象
与它关联,需要先调用Looper.prepare()创建并启用Looper。调用Looper.loop()开启循环抽取消息。
也可以handlerThread来开启子线程,因为它帮你封装了Looper对象,不需要再手动创建。并且开启了消息循环处理机制,
而Thread则不行。handlerThread解决了同步问题,它一次只接收处理一个任务。它还会提升这个子线程的优先级,
保证了在主线程调用handlerThread的hanlder对象,不会报空指针。
接下来看看handler发送消息的流程:
handler发送消息,其实就是向Messagequeue发送message,然后用Looper不断的从Messagequeue提取消息,
并且把消息回传给handler自己。至于如何回传给自己,点击跟进查看即可
详细说明:handler.sendMessage(消息);一直跟进会进入enqueueMessage()方法 ,会有 msg.target = this;
将当前创建的handler对象赋值给这个属性,然后调用queue.enqueueMessage(msg, uptimeMillis); 这个方法的作用是
入队,把每个消息及每个消息发来的时间放入消息队列中。其通过发送的时间,再根据链表的存储结构特点,把时间较短的
移动的链表的头部。
然后一直在执行的Looper.loop()方法,这里面会找到Looper对象和Messagequeue消息队列
然后会有无条件for循环取出数据,如果取出的数据不为null,则会走 Message msg = queue.next(); 如果没有消息就阻塞,
如果有消息,则取出链头的msg消息,并且移除它。然后会走(target)Handler对象调用dispatchMessage(msg)方法,
然后此方法中会判断mag.CallBack函数的返回值,若msg.callback属性不为空,则代表使用了post(Runnable r)发送消息
即回调Runnable对象里复写的run()方法,否则调用Handler自己的 handleMessage(msg);
这样就接收到了,达到了自己发给自己的效果
4、handler用法之截获
如果用handler发送消息,然后接受消息,在以下的情况是可以截获消息的,
@SuppressLint(“HandlerLeak”)
Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
会先执行这里面的代码
return false;
}
}){
@Override
public void handleMessage(Message msg) {
上面如果返回false,则会执行这个方法里的代码
上面如果返回true,则不会执行这个方法,会被上面拦截了
super.handleMessage(msg);
}
};
5、handlerThread的叙述
handlerThread设计方面比较高效快捷,它帮你把任务的发送,处理都封装了起来,包括帮你封装了
Looper对象,不需要再手动创建。而Thread则不行。
handlerThread解决了同步问题,在主线程创建此类并且获取子线程的hanlder对象,不会报空指针。
因为源码里帮这个线程提升了优先级。
6、更新UI的四种方式
(1) handler.sendmessage(msg);
(2) runOnUiThread(new Runable());
(3) handler.post(new Runable());
(4) mTv.post(new Runable(){mTv.setText(“更新内容”)});
哪有什么岁月静好,只不过有人替你负重前行.