本文包括与Handler有关的以下问题:
(1)Handler的作用
(2)为什么Android中要设计为只能在UI线程中去更新UI呢?
(3)Handler的两个异常
(4)Handler、Looper MessageQueue之间的关系(源码角度)
(5)跟线程相关的Handler,即HandlerThread(源码角度分析)
(6)主线程往子线程发消息
一、Handler的作用:
(1)在非UI线程中完成耗时操作,在UI线程中去更新UI。
(2)可以在主线程中发送延时消息。
二、为什么Android中要设计为只能在UI线程中去更新UI呢?
(1)解决多线程并发问题(根本原因)
(2)提高界面更新的性能问题
(3)架构设计的简单
你可能会说,既然是担心多线程并发问题,那我在子线程中加锁进行更新UI行不行呢?你这样想的话,会容易造成UI卡顿的,而且性能也不好。
注1:大部分面试者很难去说出一个令面试官满意的答案。
注2:关于多线程,这里举一个例子,比如说银行取款的问题。正常情况下,银行卡余额不能少于取款金额,如果多线程进行取款的话,就会造成线程不安全。
注3:Android中之所以说架构简单,是因为帮我们封装了很多更新UI的操作。
三、Handler的两个异常:
在使用Handler时,经常会出现以下两个异常:
(1)CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views:此异常是因为尝试在子线程中去更新UI,进而报错。
(2)Can’t create handle inside thread that ha not called Looper.prepared:是因为我们在子线程中去创建Handler,而产生的异常。
我们接下来通过代码来把这两个异常演示一下。
1、子线程中更新UI的异常:
(1)activity_main.xml:
上方代码中,一个文本,一个按钮,代码比较简单。
(2)MainActivity.java:
上方代码中,核心代码是第45行:点击按钮后,在子线程中更新UI。
我们来看一下后台的log日志:
上图中报的错误日志就是因为我们在子线程中去更新UI。
解决方案:
在子线程中创建Message消息,通过Handler发给主线程,之后在Handler的handleMessage方法中获得Message消息,进而处理更新UI界面。代码如下:
上方第50行代码也可以换成51行代码:
2、在子线程中创建Handler的异常:
MainActivity.java:
运行程序后, 报错如下:
非原创,参考自:http://blog.csdn.net/erliangcode/article/details/52117831