Android中Handler的工作原理

面试场景

平时开发用到过其他线程吗?都是如何处理的?

基本都用RxJava的线程调度切换,嗯对,就是那个 observeon subscribeOn 可以直接处理,比如网络操作,RxJava提供了一个叫 io 线程的处理。

在RxJava中的广泛使用之前,有使用过其他操作方式吗?比如Handler什么的?

当然用过啊

那你讲讲Handler的工作原理吧。

Handler工作流程基本包括HandlerLooperMessageMessageQueue四个部分。但我们在日常开发中,经常都只会用到Handler和Message两个类。Message负责消息的搭载,里面有个 target 用于标记消息, obj 用于存放内容,Handler负责消息的分发和处理。

一般在开发中是怎么使用Handler的?

官方不许在子线程中更新UI,所以我们经常会把需要更新UI的消息直接发给处理器Handler,通过重写Handler的 handleMessage()方法进行UI的相关操作。

那使用中就没什么需要注意的吗?

有,Handler如果设置为私有变量的话,Android studio 会报警告,提示可能会造成内存泄漏,这种情况可以通过设置为静态内部类+弱引用,或者在 onDestroy()方法中调用 Handler.removeCallbacksAndMessages (null) 即可避免;

扫描二维码关注公众号,回复: 2860796 查看本文章

正文

总的来说,这位面试的童鞋回答的也不是很差,但回答的还不是那么全面,下面我就带大家一起来分析一下吧!

首先Handler是什么呢?

在Android中表示一种消息处理机制或者叫消息处理方法,用来循环处理应用程序主线程各种消息,比如UI的更新,按键、触摸消息事件等。


为什么Android要用Handler机制?

Android应用程序启动时,系统会创建一个主线程,负责与UI组件(widget、view)进行交互,比如控制UI界面界面显示、更新等;分发事件给UI界面处理,比如按键事件、触摸事件、屏幕绘图事件等,因此,Android主线程也称为UI线程。

由此可知,UI线程只能处理一些简单的、短暂的操作,如果要执行繁重的任务或者耗时很长的操作,比如访问网络、数据库、下载等,这种单线程模型会导致线程运行性能大大降低,甚至阻塞UI线程,如果被阻塞超过5秒,系统会提示应用程序无相应对话框,缩写为ANR,导致退出整个应用程序或者短暂杀死应用程序。

Android的消息机制也就是handler机制,创建handler的时候会创建一个looper,looper一般为主线程looper,handler通过send发送消息,在send方法中handler会通过enqueueMessage方法向消息队列messagequeue中插入一条消息,同时会把本身的handler通过msg.target=this传入。looper是一个死循环,不断的读取messagequeue中的消息,loop方法会调用messagequeue的next方法来获取新的消息,next操作是一个阻塞操作,当没有消息的时候next方法会一直阻塞,当有消息的时候,looper就会通过dispatch message方法来处理消息。


handler处理消息的过程:首先,检查message的callback是否为null,不为null就通过handlecallback来处理消息,message的callback是一个runnable对象,实际上是handler的post方法所传递的runnable参数,其次是检查mcallback是否为null,不为null就调用mcallback的handlemessage方法来处理消息


除此之外,单线程模型的UI主线程也是不安全的,会造成不可确定的结果。线程不安全简单理解为:多线程访问资源时,有可能出现多个线程先后更改数据造成数据不一致。比如,A工作线程(也称为子线程)访问某个公共UI资源,B工作线程在某个时候也访问了该公共资源,当B线程正访问时,公共资源的属性已经被A改变了,这样B得到的结果不是所需要的的,造成了数据不一致的混乱情况。
线程安全简单理解为:当一个线程访问功能资源时,对该资源进程了保护,比如加了锁机制,当前线程在没有访问结束释放锁之前,其他线程只能等待直到释放锁才能访问,这样的线程就是安全的。

基于以上原因,Android的单线程模型必须遵守两个规则
1.  不要阻塞UI线程;
2.  不要在UI线程之外访问UI组件,即不能在子线程访问UI组件,只能在UI线程访问。


因此,Android系统将大部分耗时、繁重任务交给子线程完成,不会在主线程中完成,解决了第一个难题;同时,Android只允许主线程更新UI界面,子线程处理后的结果无法和主线程交互,即无法直接访问主线程,这就要用到Handler机制来解决此问题。基于Handler机制,在子线程先获得Handler对象,该对象将数据发送到主线程消息队列,主线程通过Loop循环获取消息交给Handler处理。




我所理解的也就是这样了,有理解更深刻的大佬们可以推荐小弟学习哈,谢谢哈~~~





猜你喜欢

转载自blog.csdn.net/tdltdltdl886/article/details/79892823
今日推荐