Android Handler 机制

Handler 允许你发送和处理与线程的 MessageQueue 关联的 Message 和 Runnable 对象。每个 Handler 实例都与一个线程和该线程的消息队列相关联。当你创建一个新的 Handler 时,它会绑定到一个 Looper。它会将消息和可运行对象传递到该 Looper 的消息队列,并在该 Looper 的线程上执行它们。

Handler 有两个主要用途:

1、安排消息和可运行对象在将来的某个时间执行;
2、将要在与您自己的线程不同的线程上执行的操作排入队列。
主要场景是子线程完成耗时操作的过程中,通过 Handler 向主线程发送消息 Message,用来刷新 UI 界面。

消息驱动与 Handler

Android 是消息驱动的,实现消息驱动有几个要素

消息的表示:Message

消息队列:MessageQueue

消息循环,用于循环取出消息进行处理:Looper

消息处理,消息循环从消息队列中取出消息后要对消息进行处理:Handler

初始化消息队列

在 Looper 构造器中即创建了一个MessageQueue,Looper持有消息队列的实例。

发送消息

通过 Looper.prepare 初始化好消息队列后就可以调用 Looper.loop 进入消息循环了,然后我们就可以向消息队列发送消息, 消息循环就会取出消息进行处理,在看消息处理之前,先看一下消息是怎么被添加到消息队列的。

消息循环

Java 层的消息都保存在了 Java 层 MessageQueue 的成员 mMessages 中,Native 层的消息都保存在了 Native Looper 的 mMessageEnvelopes 中,这就可以说有两个消息队列,而且都是按时间排列的。

与 Handler 工作的几个组件 Looper、MessageQueue 各自的作用:
Handler:它把消息发送给 Looper 管理的 MessageQueue ,并负责处理Looper分给它的消息
MessageQueue:管理 Message,由 Looper 管理
Looper:每个线程只有一个Looper,比如UI线程中,系统会默认的初始化一个Looper对象,它负责管理 MessageQueue,不断的从MessageQueue中取消息,并将相对应的消息分给Handler处理。

Message 属于被传递,被使用的角色。Message 是包含描述和任意数据对象的“消息”,能被发送给 Handler。Message 包含 2 个 int 属性和一个额外的对象。 虽然构造器是公开的,但获取实例最好的办法是调用Message.obtain()或Handler.obtainMessage()。这样可以从他们的可回收对象池中获取到消息实例。一般来说,每个Message实例持有一个Handler。

MessageQueue 持有一列可以被 Looper 分发的 Message。一般来说由 Handler 将 Message 添加到 MessageQueue 中。 获取当前线程的 MessageQueue 方法是Looper.myQueue()。通过 Looper.getMainLooper() 获取到主线程的 looper。

Looper 与 MessageQueue 紧密关联。在一个线程中运行的消息循环。线程默认情况下是没有与之管理的消息循环的。 要创建一个消息循环,在线程中调用 prepare,然后调用 loop。即开始处理消息,直到循环停止。大多数情况下通过Handler来与消息循环互动。

相关参考
https://mdnice.com/writing/506ba98a73114a9885c1accb9e0996b5
https://www.bilibili.com/read/cv14158988
https://zhuanlan.zhihu.com/p/532104124

Handler防止内存泄露

原因
a).声明Handler为静态类,同时对于Activity的this引用封装成WeakReference
否则会导致匿名类引用了外部Activity,导致Activity不能被回收
b).如果这时对手机硬件进行横竖屏切换,讲导致Activity被创建,却不能被回收
措施

//移除所有消息
public void onDestroy()
{
mHandler.removeCallbacksAndMessages(null);
}

//静态类 弱引用
static class MyHandler extends Handler {
    WeakReference<Activity> mActivityReference;
    MyHandler(Activity activity) {
        mActivityReference= new WeakReference<Activity>(activity);
    }
    @Override
    public void handleMessage(Message msg) {
        final Activity activity = mActivityReference.get();
        if (activity != null) {
            mImageView.setImageBitmap(mBitmap);
        }
    }
}

Handler Looper 工作原理

// 成员
class Looper {
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal()//why declare staic?
    static Looper sMainLooper
    final MessageQueue mQueue
    final Thread mThread
}

//初始化 Looper.prepare()
if(sThreadLocal.get()!=null
throw new RuntimeException
sThreadLocal.set(new Looper(true))
  
//
public Looper( boolean quitAllowed)
{
    mQueue = new MessageQueue(quitAllowed)
    mThread = Thread.currentThread()
}
 
//开启事件循环
public static Looper.loop()
{
    final Looper me = myLooper()//通过ThreadLocal获取Looper实例,通过Looper获取消息队列实例
    final MessageQueue queue = me.mQueue
    for (; ; ) {
        Message msg = queue.next()//通过消息队列阻塞性地获取消息
        if (msg == null) {// 跳出循环
            return;
        }
        try {
            msg.target.dispatchMessage(msg)//检查顺序:msg.callback->mCallback-> handleMessage
        } finally {
        }
        msg.recycleUnChecked() //初始化msg属性,并放置在Message的sPool头部
    }
}

最后Handler通过sendMessage将消息塞入mQueue队列
由Looper接收到了msg,然后调用Handler的dispatchMessage
Handler 检查mCallback->message.callback->mCallback的handleMessage

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值