Handler原理学习

前言

Handler可以说是老生常谈了,因为它在整个Android的系统中是非常重要的一部分,学习它的原理是很有必要的。本文带来的分享是对Handler原理的全面解析,相信对日常的开发和面试会有很大的帮助,下面我们一起看看它的原理。

正文

在讲解Handler原理之前,我们先通过一张图片看看它的整个流程:
在这里插入图片描述
当然,我们接下来所讲的Handler原理,不仅仅是Handler本身,还包括MessageQueue、Looper等类。

Handler的作用

在日常开发中,我们很多时候需要切换线程去做某件事情,比如在工作线程做好计算后,需要切换到主线程去更新ui,那么这个时候便可以使用Handler来进行线程的切换,又比如我们想做一个延迟任务,也可以使用Handler去开启一个延迟任务等等。

Handler

创建:

Handler的构造函数最后会调用到下面的构造函数:

public Handler(@Nullable Callback callback, boolean async) {
   

    mLooper = Looper.myLooper();
    if (mLooper == null) {
   
        throw new RuntimeException(
            "Can't create handler inside thread " + Thread.currentThread()
                    + " that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

构造函数初始化Looper成员,会对Looper进行检查,如果之前还没初始化,则会抛异常,所以创建Handler之前,需要确保当前线程的Looper已经创建了,Looper创建后会与当前线程绑定存放起来,至于它得怎么创建,我们后面会讲到。

但是我们在主线程中,则无需去创建Looper,因为在ActivityThread的main方法里边,系统已经帮我们创建好了:

//只保留核心代码
public static void main(String[] args) {
   
    Looper.prepareMainLooper();

    Looper.loop();

}

Looper.prepareMainLooper()里边会去创建一个Looper,并且这个Looper是在主线程中。

发送消息:

发送消息之前,需要创建Message,Message可以说是整个流程的载体,它承载着一些信息。它的创建方式如下:

new Message()
Message.obtain()
handler.obtainMessage()
//直接new跟obtain有什么区别呢?obtain的话,会优先到池子里拿,池子没有到话再创建一个,所以我们一般优先考虑obtain的方式去获取Message。

//发送消息
handler.sendMessage(msg);

public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
   
    // 省略校验
    return enqueueMessage(queue, msg, uptimeMillis);
}

发送消息的最后都会调用到sendMessageAtTime方法,它里边调用到是enqueueMessage方法:

private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
        long uptimeMillis) {
   
    msg.target = this;
    msg.workSourceUid = ThreadLocalWorkSource.getUid();

    if (mAsynchronous) {
   
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}

主要做了三件事:

  • 将msg的target设置为this,在消息分发时会用到,后面内容分析。
  • 如果当前Handler支持异步,那么会将msg设置为异步消息,用于异步屏障使用,后面分析
  • 调用MessageQueue的enqueueMessage方法。

下面我们一起看看MessageQueue

处理消息:

public void dispatchMessage(@NonNull Message msg) {
   
    if (msg.callback != null) {
   
        handleCallback(msg);
    } else {
   
        if (mCallback != null) {
   
            if (mCallback.handleMessage(msg)) {
   
                return;
            }
        }
        handleMessage(msg);
    }
}

从上面的代码我们可以看到分发的顺序是:

  • 如果Message有设置callback,则使用messaeg的callback进行回调,其实我们平时使用handler.post()/postDelay(),都会使用将Runnable赋值给Message的callback。
  • 如果Handler有设置callback,则会先回调Handler的callback。
  • 最后是Handler的handleMessage,这也是我们常见的一个方法,初始化Handler的时候去复写这个方法,并在里边进行消息的处理。

MessageQueue

内部时一个链表结构,用于存放Message和提供Message

插入消息:

上面讲到的enqueueMessage方法,就是用来存放Message的:

//已精简了部分代码
boolean enqueueMessage<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值