Android开发实践:由new Handler()说开去



最近面试一些Android开发的应聘者,除了基本的Activity生命周期等基础问题以外,我一般还会问如下两个问题:

(1) Service与Thread有什么区别?

(2) 在Activity里new Handler()和在自己创建的Thread中new Handler()有什么区别?

第一个问题其实是一个伪命令,因为Service是Android四大组件之一,而Thread只是Java提供的一个封装了线程管理的工具类,无论是Activity还是Service,都可以通过Thread来创建一个工作线程,但是很多新手会搞不清楚它们之间的区别,借此可以试探一下面试者到底有没有很清楚地理解Android的Service到底是做什么的。关于这个问题的答案,可以参考我的文章《Android开发实践:使用Service还是Thread》 见 http://www.linuxidc.com/Linux/2014-12/110162.htm

第二个问题,涉及到Android开发必须掌握的知识点:Handler,本文就来从这个问题开始,说说我对Handler的理解。

当Android应用启动后,系统会默认创建一个主线程(Main thread)。这个主线程启动后,首先完成UI的绘制,然后会进入一个消息循环(Loop),等待和执行各种来自系统的消息和事件、各种用户点击/触摸事件、其他线程发送的消息事件等等。这是线程工作的一种常见的模式,即进入一种“等待命令”->“执行命令/消息”->“等待命令/消息”的循环。

那么,其他非UI线程如何与进入了消息循环的主线程交互呢?这就得靠Handler了。

Handler是Android系统为工作线程提供的一种可以与外界交互的接口,通过Handler提供的sendMessage()方法,外界可以发送各种消息事件给工作线程。Handler通过构造函数完成与指定线程的绑定,其构造函数定义如下:

public Handler() {

    this(null, false);

}

 

public Handler(Looper looper) {

    this(looper, null, false);

}

 

public Handler(Looper looper, Callback callback) {

    this(looper, callback, false);

}

 

public interface Callback {

    public boolean handleMessage(Message msg);

}

其中,Looper就是线程内部负责实现消息循环的对象,普通的Java.Thread线程内部是没有这样一个消息循环对象的,Android专门提供了HandlerThread封装这种带消息循环机制的线程。Handler通过与线程的Looper对象绑定,来完成与该Thread的绑定。

Callback则是由工作线程内部传出接收到的消息的回调接口,其他线程通过Handler的sendMessage发送消息给工作线程后,工作线程就会通过Callback将接收到的消息通知给监听者。

注意:默认情况下,如果new Handler()的时候,没有传入某个线程的Looper对象(或传入null),系统就会默认绑定到创建Handler()对象的线程中。

那么,现在可以回答第二个问题了,在Activity里new Handler()和在自己创建的Thread中new Handler()有什么区别?

答案:

Activiy默认是工作在主线程中的,所以在Activity中new Handler()后,该Handler对象默认绑定了主线程的Looper对象,因此该Handler.sendMessage消息发送给了主线程,而且通过传入Callback对象得到的handleMessage()回调也是工作在主线程,这就是为什么可以通过在Activity里使用如下方式更新UI而不会导致ANR了:

new Handler( new Handler.Callback() {         

    @Override

    public boolean handleMessage(Message msg) {           

        UpdateUI();

        return false;

    }

});

同理,如果在自定义线程中 new Handler(),则默认情况该Handler()绑定了该线程的Looper对象,因此该Handler.sendMessage消息则是发送给了这个线程,而且通过传入Callback对象得到的handleMessage()回调也是工作在这个线程,因此,这种情况下的handleMessage()函数中就不能进行UI更新操作了,否则会导致ANR了。

到此为止,这个问题算是回答清楚了,但是关于Handler的解释还不够尽兴,比如线程的Looper到底是怎么工作的?下一篇文章(http://www.linuxidc.com/Linux/2014-12/110163.htm),我将用Java的Thread类,实现一个类似Looper的消息循环,以便更好地显示Android的消息循环机制。本文有任何疑问或者不清楚的地方,欢迎留言或者来信lujun.hust@gmail.com交流。

最简单的Ubuntu Touch & Android 双系统安装方式 http://www.linuxidc.com/Linux/2014-01/94881.htm

在Nexus上实现Ubuntu和Android 4.4.2 双启动 http://www.linuxidc.com/Linux/2014-05/101849.htm

Ubuntu 14.04 配置 Android SDK 开发环境 http://www.linuxidc.com/Linux/2014-05/101039.htm

64位Ubuntu 11.10下Android开发环境的搭建(JDK+Eclipse+ADT+Android SDK详细) http://www.linuxidc.com/Linux/2013-06/85303.htm

Ubuntu 14.04 x64配置Android 4.4 kitkat编译环境的方法 http://www.linuxidc.com/Linux/2014-04/101148.htm

Ubuntu 12.10 x64 安装 Android SDK http://www.linuxidc.com/Linux/2013-03/82005.htm

更多Android相关信息见Android 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=11

本文永久更新链接地址:http://www.linuxidc.com/Linux/2014-12/110161.htm

本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2014-12/110161.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值