Android中的Handler源码

Android中的Handler源码

1. 创建Message

val message = handler1.obtainMessage()
Message()
handler1.sendMessage(message)
handler1.post {}

handler1.obtainMessage(),这是复用已创建了的Message

public final Message obtainMessage()
    {
        return Message.obtain(this);
    }
    public static Message obtain(Handler h) {
        Message m = obtain();
        //在这里可以看出Message的实例会获取需要发送的Handle实例
        m.target = h;
        return m;
    }
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

这里官方解释

Return a new Message instance from the global pool. Allows us to avoid allocating new objects in many cases.
从全局池中返回一个新的Message实例。允许我们在许多情况下避免分配新对象。

我们自己也能看出从sPool的消息池中获取到Message实例,没有则创建一个新的,Message空白构造函数什么都没干。

2. 发送消息

handler1.sendMessage(message)

public final boolean sendMessage(@NonNull Message msg) {
        return sendMessageDelayed(msg, 0);
    }
public final boolean post(@NonNull Runnable r) {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

这里可以看出两种传递消息的方法都调用sendMessageDelayed,只是post中使用了getPostMessage(r)来获取了一个Message实例。

// 创建一个具有callback的Message,
// 具有callback的在dispatchMessage会执行callback内的内容。
private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

这里可以看出Message中多了一个Runnable实例。

callback 字段被设置时,Handler 处理消息时会调用这个 Runnable 对象的 run() 方法,从而执行一些额外的操作。
使用 callback 字段可以实现一些灵活的消息处理机制,例如:

  1. 延迟执行操作: 可以在 Message 中设置 callback,然后延迟一段时间发送这个消息,以便在指定的时间执行相应的操作。
  2. 在特定条件下执行操作: 当某个条件满足时,可以发送带有 callback 的消息,在 run() 方法中检查条件是否满足,然后执行相应的操作。
  3. 执行耗时操作: 可以将一些耗时的操作封装在 callback 中,在 Handler 的处理线程中执行,以避免阻塞 UI 线程。
  4. 动态修改消息处理逻辑: 可以动态地修改消息的处理逻辑,通过改变 callback 对象,使得 Handler 处理消息的方式发生变化。
    在使用 callback 字段时,需要注意避免内存泄漏问题,确保 callback 对象的生命周期不会长于需要的时间,并在不需要时及时清除。
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        // 在这里获取了当前时间加自己延迟的时间,SystemClock.uptimeMillis() + delayMillis
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() 
        + delayMillis);
    }
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);
    }
    private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
            long uptimeMillis) {
            //这里也能看出Message的target持有Handler实例
        msg.target = this;
        msg.workSourceUid = ThreadLocalWorkSource.getUid();

        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
boolean enqueueMessage(Message msg, long when) {
		......
        synchronized (this) {
        	......
            msg.markInUse();
            // 这里将发送的时间存入message中
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            // message采用链表形式,并且根据when的大小来确定插入消息队列的位置
            // 这里是判断将发送的msg放入链表头
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                .....
                // 这里找到位置并插入
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

这一流程可以看出发送消息中,会将handler实例存入message的target,有Runnable的也放入message中。消息队列是单链表,消息顺序是字段when决定的,when是在发消息时系统启动时间加上延迟时间。
MessageQueue是一个优先级队列是因为enqueueMessage方法中会根据Message的执行时间来对消息插入,这样越晚也就是when越大执行的消息会被插入到队列的后边。

public static void loop() {
        final Looper me = myLooper();
        .......

        me.mInLoop = true;

        ......
        // 这里死循环来分发消息队列中的消息
        for (;;) {
            if (!loopOnce(me, ident, thresholdOverride)) {
                return;
            }
        }
    }

3. 线程切换

loopOnce时间原因只理解了201行的msg.target.dispatchMessage(msg);
由于target是发送消息的Handler,在Handler中会根据Looper中的线程来发送到目的线程。

// 这里传入的是主线程的looper,looper中有MessageQueue的实例也会传入handler中
val handler1 = object: Handler(Looper.getMainLooper()){}
public Handler(@NonNull Looper looper) {
        this(looper, null, false);
    }
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
public void dispatchMessage(@NonNull Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

默认情况下,Handler 的 dispatchMessage() 方法会简单地调用消息对象中的 callback,如果 callback 不为 null,则执行 callback 的 run() 方法。如果 callback 为 null,则会调用 handleMessage(Message msg) 方法。
dispatchMessage() 方法的源代码通常不需要开发者自行实现,因为 Handler 类已经提供了默认实现。开发者通常只需重写 handleMessage(Message msg) 方法,来实现自定义的消息处理逻辑。但是,如果有特定需求,也可以重写 dispatchMessage() 方法,以实现更灵活的消息处理机制。
接下来解决线程切换问题
在Looper类中维持着

    static final ThreadLocal<Looper> sThreadLocal = 
    						new ThreadLocal<Looper>();
    private static Looper sMainLooper;
    public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
    //每一个线程只能调用一次prepare()
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

可以看出每一个线程只维持这一个Looper,但是其中始终包含了一个主线程Looper在其中

public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }

4. 其他创建一个Looper

thread {
            Looper.prepare()
            val messageQueue = MessageQueue()
            val handler2 = object: Handler(Looper.myLooper()!!){
                override fun dispatchMessage(msg: Message) {
                    super.dispatchMessage(msg)
                }

                override fun handleMessage(msg: Message) {
                    super.handleMessage(msg)
                }
            }
            Looper.loop
            Log.i("TAG", "onCreate: ${handler2.looper}")
        }
  • 44
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值