Handler详解
来源:互联网 发布:淘宝店花呗怎么开通 编辑:程序博客网 时间:2024/06/02 01:06
Handler10问10答:
1.什么是Handler?
Handler是Android消息机制上层接口2.Handler的作用?
将一个任务切换到某个指定的线程中去执行
3.Android为什么要提供Handler?
因为Android规定访问UI只能在主线程中进行,但是又不能在主线程中进行耗时操作,
否则会导致ANR,因此系统提供了Handler来解决该问题
4.系统为什么不允许在子线程中访问UI呢?
答:因为Android的UI控件不是线程安全的,如果在多线程中并发访问可能导致UI控件处于不可预期的状态
5.Handler机制是靠什么支撑的?
答:MessageQueue 和 Looper
6.什么是MessageQueue,它的作用是什么?
答:顾名思义,MessageQueue是消息队列,
它的作用只有两个:
a.通过调用equeueMessage()方法,往消息队列中插入一条消息;
插入消息的操作是通过单列表的方式;
b.通过调用next()方法,从消息队列中取出一条消息,并从消息队列中移除;
它是一个死循环的方法,如果没有消息,next()方法会一直阻塞在这里;
7.什么是Looper,它的作用是什么?
答:可以看到,MessageQueue只是用来插入和取出消息的,并不能处理消息,这个时候
Looper就出现了来弥补这个功能;
Looper通过调用prepare()方法来创建当前线程的Looper对象
并通过调用loop()方法开启处理消息死循环模式
在loop()方法中MessageQueue调用next()方法来取出一个又一个的消息,
并调用了Handler.dispatchMessage()方法来处理消息
8.Handler是怎么把任务切换到指定线程中的呢?
答:由于Handler.dispatchMessage()方法是在创建Handler时所使用的Looper中执行的,自然而然将代码逻辑切换到指定的线程中去了
9.Handler的工作原理是什么?
答:Handler主要包含消息的发送和接收
发送消息通过:post或者sendMessage方法
10.使用Handler必须为线程创建Looper,为什么我们在主线程中却没有创建呢?
答:这是因为Android的主线程也就是ActivityThread,入口方法为main(),
在main方法中系统会通过Looper.prepareMainLooper()来创建主线程的Looper
以及MessageQueue,并通过Looper.loop()开启主线程的循环
☆☆☆
相信很多人都会用Handler,但你写的真的没有问题吗?
你有考虑过使用Handler可能造成的内存溢出的问题吗?
下面写一个标准代码解决Handler可能造成的溢出问题:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //使用handler延时2分钟执行一个任务(为了测试) mHandler.postDelayed(new Runnable() { @Override public void run() { } }, 1000 * 60 * 2); //之后关闭activity finish(); } private MyHanlder mHandler = new MyHanlder(this); /** * 不能让Handler持有Activity的强引用 * 不然,就算Activity调用了finish方法 * 垃圾回收器依然不会回收它,这样,就可能 * 造成内存泄漏,最终可能导致内存溢出。 */ private static class MyHanlder extends Handler { WeakReference<MainActivity> weakReference; public MyHanlder(MainActivity mainActivity) { //将Activity的引用变为弱引用 weakReference = new WeakReference<MainActivity>(mainActivity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); //获取Activity的强引用 MainActivity mainActivity = weakReference.get(); //如果Activity没有被垃圾回收器回收 if (mainActivity != null) { //这个时候在做一些操作即可 } } }}详解:
当使用内部类(包括匿名类)来创建Handler的时候,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用(不然你怎么可能通过Handler来操作Activity中的View?)。而Handler通常会伴随着一个耗时的后台线程(例如从网络拉取图片)一起出现,这个后台线程在任务执行完毕(例如图片下载完毕)之后,通过消息机制通知Handler,然后Handler把图片更新到界面。然而,如果用户在网络请求过程中关闭了Activity,正常情况下,Activity不再被使用,它就有可能在GC检查时被回收掉,但由于这时线程尚未执行完,而该线程持有Handler的引用(不然它怎么发消息给Handler?),这个Handler又持有Activity的引用,就导致该Activity无法被回收(即内存泄露),直到网络请求结束(例如图片下载完毕)。另外,如果你执行了Handler的postDelayed()方法,该方法会将你的Handler装入一个Message,并把这条Message推到MessageQueue中,那么在你设定的delay到达之前,会有一条MessageQueue -> Message -> Handler -> Activity的链,导致你的Activity被持有引用而无法被回收。
- Handler详解
- Handler详解
- Handler详解
- Handler详解
- handler详解
- Handler详解
- Handler详解
- Handler详解
- Handler详解
- Handler 详解
- Handler详解
- Handler详解
- Handler详解
- Handler详解
- Handler详解
- Handler详解
- Handler详解
- Handler详解
- 分布式消息系统:Kafka
- 书籍下载列表
- Unity和Android交互案
- C++实验6
- jQuery中.bind() .live() .delegate() .on()区别
- Handler详解
- AndroidStudio2.3.2升级后工程打开失败解决
- Spark实战之读写HBase
- {题解}[jzoj5097]【GDOI2017 day1】取石子游戏
- mysql数据表操作
- jsp杂记
- Thinking in Java 笔记
- 常用排序算法总结(插入、冒泡、快速,堆、选择、希尔、归并)
- JS处理包含readonly属性的下拉框直接赋值