Android 中Handler 详解

本文深入探讨了 Android 中 Handler 的工作机制,包括其构造函数、消息队列的搭建及消息处理流程。文章还详细解释了如何使用 sendMessage 和 obtainMessage 方法,并介绍了如何处理 Runnable 和 Message 对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

版本基于:Android R

之前 
Android 基于Handler 剖析消息机制 一文中完成地剖析了Android 中异步消息处理的流程。

0. 前言

Handler 的描述很详细:

/**
 * A Handler allows you to send and process {@link Message} and Runnable
 * objects associated with a thread's {@link MessageQueue}.  Each Handler
 * instance is associated with a single thread and that thread's message
 * queue. When you create a new Handler it is bound to a {@link Looper}.
 * It will deliver messages and runnables to that Looper's message
 * queue and execute them on that Looper's thread.

Handler 是用来发送和处理与一个线程的 MessageQueue 有关联的 Message 和 Runnable。

一个 Handler 与一个线程以及此线程的MessageQueue有关联。

新建一个Handler 的时候,要与一个 已经创建好的线程 的 MessageQueue 绑定。这样Handler 就可以发送message 和runnable 到消息队列,并且处理从消息队列发出来的回调。

1. 构造函数

Handler 类的构造函数有7 个,但是最终可以提炼出两个,以参数有无looper 区分。

主要来看一下:

frameworks/base/core/java/android/os/Handler.java

    public Handler(@Nullable Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }
 
        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;
    }
    public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

通过构造函数可以看到,handler 是创建的时候可以不传Looper,那也就是说这个时候的handler 是在实例它的线程 Looper.myLooper() 中。

在应用中可能一些费时、阻塞的东西可以通过消息队列来处理,这个时候可以新建一个Thread,将Thread 中处理消息队列,最后通过 handleMessage() 在主线程中处理UI 的操作。

2. 搭建消息队列

通过 Handler sendMessage 与 obtainMessage (sendToTarget)比较 看到,我们还是尽量用obtainMessage() 来获取msg obj:

frameworks/base/core/java/android/os/Message.java

    public final Message obtainMessage(int what)
    {
        return Message.obtain(this, what);
    }

至于new Message() 与obtainMessage() 有什么区别,可以看一下Handler sendMessage 与 obtainMessage (sendToTarget)比较

sendMessage() 有两个选择:

  • 通过自身线程的Handler发送消息,消息会存放在本线程的MessageQueue中
  • 通过另外线程的Handler发送消息,消息会存放在另外线程的MessageQueue中
frameworks/base/core/java/android/os/Message.java

    public void sendToTarget() {
        target.sendMessage(this);
    }

最终会调用到:

frameworks/base/core/java/android/os/Handler.java

    public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

最终会往handler 所在的Lopper 里面的MessageQueue 存msg。

通过 Android 基于Handler 剖析消息机制 知道 Looper.loop() 就是一直处理消息队列,没有就挂靠起来。loop 会去处理每一个msg:

msg.target.dispatchMessage(msg);
frameworks/base/core/java/android/os/Handler.java

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

这个逻辑也是需要注意的:

  • 当Message 中有Runnable 处理的时候,会去处理Runnable

该 Runnable 可以通过Handler 中的接口设置,最终都是通过 Message.obtain() 存入到 message 中,如下:

frameworks/base/core/java/android/os/Handler.java

public final boolean post(Runnable r)
{
   return  sendMessageDelayed(getPostMessage(r), 0);
}

public final boolean postAtTime(Runnable r, long uptimeMillis)
{
    return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}

public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
{
    return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}

public final boolean postDelayed(Runnable r, long delayMillis)
{
    return sendMessageDelayed(getPostMessage(r), delayMillis);
}

public final boolean postAtFrontOfQueue(Runnable r)
{
    return sendMessageAtFrontOfQueue(getPostMessage(r));
}

    private static Message getPostMessage(Runnable r, Object token) {
        Message m = Message.obtain();
        m.obj = token;
        m.callback = r;
        return m;
    }
  • 如果没有Runnable 有Callback 的时候,处理Callback
    public interface Callback {
        public boolean handleMessage(Message msg);
    }
  • 如果上面都没有,如果需要处理msg,就需要override handler 中的成员函数
    public void handleMessage(Message msg) {
    }


删除Runnable 和 msg 可以通过:

public final void removeCallbacks(Runnable r)
{
    mQueue.removeMessages(this, r, null);
}

public final void removeCallbacks(Runnable r, Object token)
{
    mQueue.removeMessages(this, r, token);
}
public final void removeMessages(int what) {
    mQueue.removeMessages(this, what, null);
}

public final void removeMessages(int what, Object object) {
    mQueue.removeMessages(this, what, object);
}


还有一个Android 类可以直接用,可以看一下 Android HandlerThread

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

私房菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值