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》


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


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


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


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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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了:


1
2
3
4
5
6
7
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到底是怎么工作的?下一篇文章,我将用Java的Thread类,实现一个类似Looper的消息循环,以便更好地显示Android的消息循环机制。



本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/1564550,如需转载请自行联系原作者。


相关文章
|
13天前
|
缓存 搜索推荐 Android开发
安卓开发中的自定义控件实践
【10月更文挑战第4天】在安卓开发的海洋中,自定义控件是那片璀璨的星辰。它不仅让应用界面设计变得丰富多彩,还提升了用户体验。本文将带你探索自定义控件的核心概念、实现过程以及优化技巧,让你的应用在众多竞争者中脱颖而出。
|
13天前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
32 2
|
1天前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
9 1
|
4天前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
23 2
|
12天前
|
缓存 搜索推荐 Android开发
安卓开发中的自定义控件基础与进阶
【10月更文挑战第5天】在Android应用开发中,自定义控件是提升用户体验和界面个性化的重要手段。本文将通过浅显易懂的语言和实例,引导你了解自定义控件的基本概念、创建流程以及高级应用技巧,帮助你在开发过程中更好地掌握自定义控件的使用和优化。
25 10
|
4天前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
24 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
12天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异:从代码到用户体验
【10月更文挑战第5天】在移动应用开发的广阔天地中,安卓和iOS两大平台各占半壁江山。它们在技术架构、开发环境及用户体验上有着根本的不同。本文通过比较这两种平台的开发过程,揭示背后的设计理念和技术选择如何影响最终产品。我们将深入探讨各自平台的代码示例,理解开发者面临的挑战,以及这些差异如何塑造用户的日常体验。
|
9天前
|
消息中间件 存储 前端开发
资深Android开发的5个经典面试题
本文首发于公众号“AntDream”,欢迎关注。文章详细解答了五个常见的Android面试题,涵盖内存泄漏与溢出、Binder机制、MVC/MVP/MVVM架构、Handler机制及Context对象等内容,帮助读者深入了解Android开发的核心概念。
16 0
|
9天前
|
存储 安全 Android开发
探索Android开发之旅:从新手到专家的蜕变之路
【10月更文挑战第8天】在这篇文章中,我们将共同踏上一段激动人心的旅程,深入探索Android开发的奥秘。无论你是初涉编程世界的新手,还是渴望提升技能的开发者,这里都有你需要的知识与启示。通过简洁明了的语言和实际案例,我们将一起解锁Android开发的核心概念、掌握关键技能,并最终实现从新手到专家的华丽转变。
|
10天前
|
Android开发
Android开发显示头部Bar的需求解决方案--Android应用实战
Android开发显示头部Bar的需求解决方案--Android应用实战
13 0