《面试总结》Android消息机制、Handler机制

本文只作总结,不写细节,可用于面试知识点快速复习。

需要深入了解细节的朋友请看完总结后带着问题去百度。

Handler

Android特有的线程间通信方式,适用于任意两个线程之间的通信,主要是发送和处理消息,使用场景一般为子线程异步任务回调到主线程中的Handler的回调方法中进行UI操作。

向主线程提交消息的方式

  1. Handler.sendMessage(Message message)
  2. View.post(Runnable runnable)

Message的初始化方式

  1.  直接new Message(),会实例化一个新的消息对象。
  2. Message.obtain() : 可能会复用消息对象,使用obtain获取Message对象是因为Message内部维护了一个数据缓存池,回收的Message不会被立马销毁,而是放入了缓存池, 在获取Message时会先从缓存池中去获取,缓存池为null才会去创建新的Message。

Handler使用中可能导致内存泄漏的情况

Handler使用是用来进行线程间通信的,所以新开启的线程想要发送消息到其他线程是会持有Handler引用的, 如果在Activity等组件中创建Handler,并且是非静态内部类的形式,就有可能造成内存泄漏,因为非静态内部类默认持有外部类的对象即Activity等组件的对象,如果子线程中进行耗时任务迟迟不能销毁,那么Handler对象也不能销毁,则导致Activity等组件也无法及时销毁,导致内存泄漏。

同时,MessageQueue中如果存在未处理完的Message,Message的target就是Handler的对象,也持有Activity等组件的引用,也会造成内存泄漏。

解决办法是通过静态内部类形式的handler,如果需要使用Activity的引用,则通过构造方法将Activity的引用传参到handler中以WeakReference(一旦发生GC,则会回收弱引用)的形式保存。

Android应用消息机制

在使用Handler的时候,Handler对象的实例化需要一个线程具有Looper对象,Android应用的主线程(UI线程,ActivityThread,可以理解为一个java文件执行时默认的线程)在初始化的时候会默认初始化Looper(Looper.prapare()方法初始化,Looper存放在线程的ThreadLocal中,ThreadLocal是线程用于存放私有变量的地方),Looper的内部会初始化一个MessageQueue对象(单链表形式,插入和删除上有优势)用于存储通过Handler发送到主线程的所有消息(Message类,分为同步消息和异步消息),然后Looper执行Looper.loop()方法开始死循环调用MessageQueue.next()方法获取Message并执行,如果MessageQueue为空则主线程阻塞,Message的执行会回调相应的Handler的handleMessage方法体或者对应Runnable的run方法(Runnable通过view.post()方法提交到MessageQueue)。

MessageQueueLooper、Handler的关系

MessageQueue和Looper是一对一的关系,Handler和Looper是多对一的关系。

子线程使用Handler的方法

必须在子线程中使用Looper.prapare()初始化Looper对象,然后调用Looper.loop()方法开启消息死循环,并且在实例化Handler时使用new Handler(Looper looper)的构造方法将Looper对象与Handler绑定,MessageQueue对象会在Looper对象的构造方法中被初始化。 Android中提供HandlerThread类提供默认已经初始化looper对象的线程。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值