提出问题
现在这里列出几个问题,思考一下:
- Handler的作用
- 为什么Android中要设计为只能在UI线程中去更新UI呢?
- 说说Handler、Looper MessageQueue之间的关系
- 主线程往子线程发消息
- 子线程中可以使用Handler吗?
- 可以在非主线程中更新UI吗?
- 使用Handle要注意什么(会引发什么问题)?
问题分析
以上几个问题如果都能回答的上来,说明关于Handle你已经基本掌握了,如果还有点模糊的话可以先看下以下两篇文章:
ok,现在先看第一个问题:
Handler的作用
- 接收消息:在非UI线程中完成耗时操作,在UI线程中去更新UI。
- 发送消息:可以在主线程中发送延时消息。
为什么Android中要设计为只能在UI线程中去更新UI呢?
从源码的角度来回答:
我们知道既然是要更新UI,那么一定会涉及到View的绘制,既然要绘制View,那么一定会调用ViewRootImpl. ()方法,requestLayout()方法,里面都会调用checkThread();里面就对当前是否是主线程进行判断。如果不是主线程,就会抛异常。1234567891011121314public void requestLayout() {//我们在自定义ViewGroup的时候,如果要更新布局就会调用这个方法刷新界面,其实就是调用了View的重新绘制流程。if (!mHandlingLayoutInLayoutRequest) {checkThread();mLayoutRequested = true;scheduleTraversals();}}void checkThread() {if (mThread != Thread.currentThread()) {//非主线程抛异常throw new CalledFromWrongThreadException("Only the original thread that created a view hierarchy can touch its views.");}}从设计思想的角度来回答:
- 解决多线程并发问题(根本原因)
在子线程中加锁也可以解决并发的问题,可是会造成UI卡顿的新问题,性能低下,所以不能加锁。 - 提高界面更新的性能问题
- 架构设计的简单
说说Handler、Looper MessageQueue之间的关系

这里的话我举个例子来回答:在一个流水线生产车间中,整个大的机器就是Looper(一直在工作状态),而传送带就是MessageQueue,有货物(Massage)时,就会一直传送(Loop循环),机器处理这些货物(Massage)。没有货物(Massage)时就机器就关闭(主线程进入休眠状态),因为节省成本要省电(释放CPU资源),而工人(Handle)负责把货物(Massage)放到传送带上(Handler.sendMessage(Message))。
这个例子不知道贴不贴切。。。
主线程往子线程发消息
我们用的最多的就是子线程向主线程发送消息,那如何让主线程给子线程发送消息呢?
由此可见可以在子线程中创建使用Handle的,但是以下写法是不对的:
Handle.class:
以上会有 “Can’t create handler inside thread that has not called Looper.prepare()”的错误。
所以要在子线程中创建Handle的话必须要执行Looper的prepare()方法,生成Looper对象,把Looper对象和当前线程对象形成键值对(线程为键),存放在ThreadLocal当中,然后生成handler对象,调用Looper的myLooper()方法,mLooper就不会为null了,得到与Handler所对应的Looper对象。handler、looper 、消息队列就形成了一一对应的关系
可以在非主线程中更新UI吗?
可以吗?答案是可以的。要从源码的角度来分析就很好理解。
还是说回View的绘制吧,刚刚也说了View的绘制肯定会调用CheckThread()方法,不是主线程的话肯定会执行不下去的。那好,我们想想,当我们开启一个Activiy的时候,在哪个生命周期方法中开始View的绘制的,是在onCreate()吗?我们看了源码就会知道是在onRsume()中才开始绘制View的:
所以,我们只要在onResume方法之前,比如说在onCreate方法中:
以上代码可直接运行。