在安卓中,出于性能优化的考虑,UI线程操作并不安全,于是Android制定了一个规则:只允许UI线程修改Activity里的组件。但是这条规则又导致了另外一个问题,因为在Android平台上只允许UI线程修改Activity里的UI组件,导致新启动的线程无法动态改变界面组件的属性值。但这并不满足开发者的需求,特别是游戏开发者,因为需要让新启动的线程周期性地改变界面组件的属性值,因此就需要Handler的消息传递机制来实现了。
而说到Handler,不得不提的还有与Handler一起工作的组件,Looper和MessageQueue。
每个线程中只能有一个Looper类,它有一个loop方法负责读取MessageQueue中的消息,读到信息之后就把发送该消息的Handler进行处理。而MessageQueue,也就是消息队列,它是采用先进先出的方式来管理Message,根据Looper构造器的源代码就可以看到在创建Looper对象时就在它的构造器中创建了MessageQueue对象,源代码如下:
private Looper () {
mQueue = new messageQueue();
mRun = true;
mThread = Thread.currentThread();
}
在我们的主线程中,系统初始化了一个Looper现象,程序可以直接创建Handler并通过它发送、处理消息。
通过对Looper的理解,我们也就知道Handler类的作用,也就是在新启动的线程中发送消息和在主线程里面获取、处理消息。可是什么时候该去主线程获取并处理消息呢?这个时候很显然,只能依赖于回调的方式。也就是说,我们只需要重写Handler类中处理消息的方法,当新启动的线程发送消息时,消息会发送与之关联的消息队列中,然后Handler就会不断地从消息队列中获取并处理消息。如下面的代码所示:我们新建了一个Handler的对象,通过dispatchMessage()方法获得消息队列中的message,根据不同的message对界面进行处理:
private Handler mHandler = new Handler() {
public void dispatchMessage(Message msg) {
switch (msg.what) {
case WHAT_REFRESH_SUCCEED:
setHomeViewData(); // 设置首页中的数据
mLoadingView.dismiss(); // 关闭加载框
break;
------------------略------------------------------------------
default: } } };如上面的代码所示,如果从消息队列获得的消息为WHAT_REFRESH_SUCCEED,那么我们就执行下面一系列的方法,这些方法就不多说了,总是就是和界面UI布局相关的。而在代码的其他一些地方我们可以通过Handler的一些方法发送消息。
Handler类中有下面几种方法用于发送、处理消息:
(1)void handlerMessage(Message msg):这是处理消息的方法,通常用于被重写。
(2)final boolean hasMessage(int What):这个方法是用于检查消息队列中是否包含what属性为指定值的消息。
(3)final boolean hasMessage(int what, Object object):这个方法是用于检查消息队列中是否包含what属性为指定值并且object属性为指定对象的消息。
(4)Message obtainMessage():这个方法是用于获取消息。
(5)sendEmptyMessage(int what):发送空消息,实际上上面就有用到,这个what就是我们的WHAT_REFRESH_SUCCEED。
(6)final boolean sendEmptyMessageDelayed(int what, long delayMillis):这个方法就是指定多少毫秒后发送空消息
(7)final boolean sendMessage(Message msg):立即发送消息
(8)final boolean sendMessageDelayed(int what, long delayMillis):这个方法就是指定多少毫秒后发送消息
在上面的方法中,我们发现(5)和(7)很相似,那么他们有什么区别呢?经过查询资料,我才知道,在sendMessage中就是构建了一个Message,然后把这个Message的what设置成sendEmptyMessage方法中的What参数即可。
也就是说当我们使用sendMessage()方法时,我们新建一个Message对象,然后再调用这个对象,类似于下面代码所示:
Message msgObj = mHandler.obtainMessage(WHAT_REFRESH_SUCCEED, model);
mHandler.sendMessage(msgObj);
而我们调用sendEmptyMessage()时,只要直接在里面传一个WHAT_REFRESH_SUCCEED即可,这些都是要根据不同的情况而定,当然在Handler里面的处理也会有一些差别。这就是我近期对Handler的一些学习理解和应用,有错误的地方欢迎指正。