0
点赞
收藏
分享

微信扫一扫

Android 消息机制之消息的其他处理深入源码分析 [ 九 ]

Android 消息机制深入源码分析 [ 一 ]
Android 消息机制之 ThreadLocal 深入源码分析 [ 二 ]
Android 消息机制之 Looper 深入源码分析 [ 三 ]
Android 消息机制之 Message 与消息对象池的深入源码分析 [ 四 ]
Android 消息机制之 MessageQueue 深入源码分析 [ 五 ]
Android 消息机制之初识Handler [ 六 ]
Android 消息机制之 Handler 发送消息的深入源码分析 [ 七 ]
Android 消息机制之 MessageQueue.next() 消息取出的深入源码分析 [ 八 ]
Android 消息机制之消息的其他处理深入源码分析 [ 九 ]
Android 消息机制总结 [ 十 ]

上一章分析学习了消息机制中重要的取出操作, 本章对剩余消息分发处理, 移除, 查看消息是否存在等的分析.
先来看消息的分发处理.

1. Handler.dispatchMessage(Message msg)

Looper.loop() 方法内调用. 先从 MessageQueue 中获取到一个消息后, 再调用这个方法传入获取的消息进行分发处理.
Handler.java 97 行.

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        //当 Message 存在回调方法, 回调 msg.callback.run() 方法
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            //当创建 Handler 时, 传入的参数为 Callback 的时候, , 回调方法为 Handler.Callback.handleMessage()
            //在第六篇中有分析到这个 Callback.
            //如果我们实现的 Callback 接口中 handleMessage 返回 true, 则表示不会调用 Handler 自身的 HandleMessage() 方法.
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        //Handler 自身的回调方法 handlerMessage()
        handleMessage(msg);
    }
}

在分发消息三个方法啊的优先级

  • Message 的回调方法优先级最高. 既 message.callback.run()
  • Handler 的回调方法次之, 既 Handler.Callback.handleMessage
  • Handler 的默认方法优先级最低.

很多情况下, 消息分发后的处理都是第三种情况, 一般往往都是通过复写第三种方法, 从而实现自己的业务逻辑.

 

2. 消息的移除

消息的移除其实就是根据身份 what / Runnable / msg.obj 移除队列中对应的消息, 例如发送消息时, 用同一个 msg.what 作为参数, 所有方法最终调用 MessageQueue.removeMessages 来操作.

调用方法的入口依然是在 Handler.java 中

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);
}

public final void removeCallbacksAndMessages(Object token) {
  mQueue.removeCallbacksAndMessages(this, token);
}

不难看出 Handler 中的删除工作, 其实都是通过调用 MessageQueue 来操作的.
MessageQueue 中的消息移除又有以下几个方法

void removeMessages(Handler , int , Object )
void removeMessages(Handler, Runnable,Object)
void removeCallbacksAndMessages(Handler, Object)
void removeAllMessagesLocked()
void removeAllFutureMessagesLocked()

先来看第一个.

MessageQueue.removeMessages(Handler , int , Object )
MessageQueue.java 641 行

void removeMessages(Handler h, int what, Object object) {
    //分析 1
    if (h == null) {
        return;
    }
    synchronized (this) {
        //分析 2
        Message p = mMessages;

        //分析 3
        while (p != null && p.target == h && p.what == what&& (object == null || p.obj == object)) {
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();
            p = n;
        }
        //分析 4
        while (p != null) {
            Message n = p.next;
            if (n != null) {
                if (n.target == h && n.what == what && (object == null || n.obj == object)) {
                    Message nn = n.next;
                    n.recycleUnchecked();
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}
  • 分析

 
从消息队列中移除 Message 的操作就是遍历消息队列然后移除所有符合条件的 Message. 但是这里有个细节. 从代码中可以看出移除是分了两步操作. 第一次先判断符合删除条件的 Message 是不是从消息队列的头部就开始有了, 这时候会修改 mMessage 指向的问题, 而 mMessage 代表的就是整个消息链表, 排除了第一种情况之后, 剩下的就是继续遍历队列移除剩余符合条件的 Message, 其他重载方法也基本类似这样的流程, 不同的就是条件不同而已. 下面直接分析 removeAllFutureMessagesLocked() 这个方法.
 
MessageQueue.removeAllFutureMessagesLocked()
MessageQueue.java 752 行.

private void removeAllFutureMessagesLocked() {
    //分析 1
    final long now = SystemClock.uptimeMillis();
    //分析 2
    Message p = mMessages;
    if (p != null) {
        //分析 3
        if (p.when > now) {
            removeAllMessagesLocked();
        } else {
            //分析 4
            Message n;
            for (;;) {
                n = p.next;
                if (n == null) {
                    return;
                }
                if (n.when > now) {
                    break;
                }
                p = n;
            }
            //分析 5
            p.next = null;
            do {
                p = n;
                n = p.next;
                p.recycleUnchecked();
            } while (n != null);
        }
    }
}

删除所有未来的消息.

  • 分析

 

3. 查看消息是否存在

入口同样也是在 Handler 中. 有 3 个入口

// Handler.java
public final boolean hasMessages(int what) {
    return mQueue.hasMessages(this, what, null);
}

public final boolean hasMessages(int what, Object object) {
    return mQueue.hasMessages(this, what, object);
}

public final boolean hasCallbacks(Runnable r) {
    return mQueue.hasMessages(this, r, null);
}

内部同样调用的也是 MessageQueue.hasMessages 方法.

MessageQueue.hasMessages(Handler h, int what, Object object)
MessageQueue.java 590 行

boolean hasMessages(Handler h, int what, Object object) {
    //分析 1
    if (h == null) {
        return false;
    }
    synchronized (this) {
        //分析 2
        Message p = mMessages;
        //分析 3
        while (p != null) {
            if (p.target == h && p.what == what && (object == null || p.obj == object)) {
                return true;
            }
            p = p.next;
        }
        return false;
    }
}
  • 分析

剩下的也都基本是这个流程, 就不再分析. 不同的只是筛选条件不同.

到这里, Android 消息机制的 消息入队, 消息取出, 消息处理, 消息移除, 已经全部分析学习完了, 下一章将学习一个新的内容 HandlerThread.

举报

相关推荐

0 条评论