Android的消息机制(二)

68 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情

3.消息机制的分析

1.了解Message

可理解为线程间通讯的数据单元,可通过message携带需要的数据 创建Message的方法

  1. val message:Message= Message()
  2. val message1:Message=Message.obtain()//它利用了Message中消息池(sPool)

封装数据:

int what:标识

int arg1:保存int数据

int arg2:保存int数据

Object obj:保存任意时刻的数据

Long when :记录应该被处理的时间值,若为即时消息,时间值=发送时间,若为延时消息,时间值=发送时间+延迟时间

Handler target:用来处理消息的Handler对象,就是发送消息的Handler

Runnable callback:用来处理消息的回调器

Message next:指向下一个Message用来形成一个链表

Message sPool:用来缓存处理过的Message,以便复用

2.了解Handler

Handler是Message的处理器,同时也负责消息的发送和移除的工作

(1)Handler的构造方法

Android API 30以上,使用Handler()方法时会显示删除线,并提示相关的方法已经被弃用,不建议使用。如图所示:

image.png

但是安卓不是弃用Handler这个类,而只是弃用Handler的两个构造方法:

1.  Handler()
1.  Handler(callback:Handler.Callback)

安卓建议采用如下方法来解决

1.使用Executor

2.明确指定Looper

3.使用Looper.getMainLooper()定位并使用主线程的Looper

4.如果又想在其他线程,又想要不出bug,请使用Handler(looper:Looper)或者Handler(Looper.myLooper())这两个构造方法。

(2)Handler导致的内存泄漏问题

在Android中最常用的一种内存泄漏是Handler导致的泄漏,原因:

(1)在Activity被摧毁时,延迟消息还没发出,Handler可能有未执行完或者正在执行的Message,MessagesQueue就会持有这个消息的引用,导致Handler持有Activity的引用,进而导致GC无法回收Activity。

(2)Handler中有还没执行完的Message,还在运行,而运行中的子线程不会被回收,所以就导致了内存泄漏。

解决方法:

1.在Activity的onDestroy()方法中,清空Handler中的未执行或者正在执行的Message和Callbacks

1.  override fun onDestroy() {
1.  super.onDestroy()
1.  handler.removeCallbacksAndMessages(null)
1.  }

2.static+弱引用

class  MyHandler(activity: HandlerActivity):Handler(Looper.getMainLooper()){
        private val myWeakReference:WeakReference<HandlerActivity> = WeakReference(activity)
        override fun handleMessage(msg: Message) {//处理消息的回调方法
            myWeakReference.get()?.run {
            ...
        }
      }
 }

(3)Handler的常用方法:

发送即时消息:sendMessage(msg Message)

发送延时消息:sendMessageDelayed(msg Message,delayMillis Long)

处理方法:handleMessage(msg Message)(回调方法)

移除还未处理的消息:removeMessages(what int)