android Handler消息原理详情

Message对象

Message对象是需要被执行的对象,Message实例对象取得,通常使用Message类里的静态方法obtain(),该方法有多个重载版本,它创建并不一定创建一个新的Message实例,会有返回之前回收回来的对象。

Message Queue中存放着多个Message消息,是消息的管理者,每个线程。有且只有一个实例

Looper对象

每一个Looper对象和一个线程关联。通过调用Looper.myLooper()可以获得当前线程的Looper对象,创建一个Looper对象时,会同时创建一个MessageQueue对象。除了主线程有默认的Looper,会同时创建一个MessageQueue对象。除了主线程有默认的Looper,其它线程默认是没有MessageQueue对象的。所以不能接受Message。如需要接受,自己定义一个Looper对象,这样的该线程就有了自己的Looper对象和MessageQueue数据结构。
Looper从MessageQueue中取出Message然后,交由Handler的HandlerMessage进行处理。处理完成后,调用Message.recycle()将其放入MessagePool中。

Handler对象

消息处理者,handler负责将需要传递的信息封装成Message,通过调用ObtainMessage()来实现;
将消息传递给MessageQueue,然后通过转线程Looper通过MessageQueue获取Message消息,并将其通过dispatchMessage发送出去

创建Handler对象

 1  public Handler(Callback callback, boolean async) {
 2         mLooper = Looper.myLooper();
 3         if (mLooper == null) {
 4             throw new RuntimeException(
 5                 "Can't create handler inside thread that has not called Looper.prepare()");
 6         }
 7         mQueue = mLooper.mQueue;
 8         mCallback = callback;
 9         mAsynchronous = async;
10     }

获取当前线程的Looper

public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

Message创建对象
    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();
    }

Message销毁对象
    void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        sendingUid = -1;
        when = 0;
        target = null;
        callback = null;
        data = null;

        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }

发送消息
Handler发送消息的方式有二种:
1. sendMessage
2. Post(Runnable)
sendMessage消息是在HandlerMessage方法中执行
Post消息是在message.callback.run();方法中执行
 1 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
 2         MessageQueue queue = mQueue;
 3         if (queue == null) {
 4             RuntimeException e = new RuntimeException(
 5                     this + " sendMessageAtTime() called with no mQueue");
 6             Log.w("Looper", e.getMessage(), e);
 7             return false;
 8         }
 9         return enqueueMessage(queue, msg, uptimeMillis);
10     }
11 
12 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
13     msg.target = this;
14     if (mAsynchronous) {
15         msg.setAsynchronous(true);
16     }
17     return queue.enqueueMessage(msg, uptimeMillis);
18 }

 线程消息执行

 1 public static void loop() {
 2         final Looper me = myLooper();
 3         if (me == null) {
 4             throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
 5         }
 6         final MessageQueue queue = me.mQueue;
 7 
 8         // Make sure the identity of this thread is that of the local process,
 9         // and keep track of what that identity token actually is.
10         Binder.clearCallingIdentity();
11         final long ident = Binder.clearCallingIdentity();
12 
13         for (;;) {
14             Message msg = queue.next(); // might block
15             if (msg == null) {
16                 // No message indicates that the message queue is quitting.
17                 return;
18             }
19 
20             final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
21 
22             final long traceTag = me.mTraceTag;
23             if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
24                 Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
25             }
26             final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
27             final long end;
28             try {
29                 msg.target.dispatchMessage(msg);
30                 end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
31             } finally {
32                 if (traceTag != 0) {
33                     Trace.traceEnd(traceTag);
34                 }
35             }
36             msg.recycleUnchecked();
37         }
38     }

Handler执行线程

当Handler的mCallback有设置时优化执行,否则执行Handler的handleMessage函数
/**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

 

//Post消息执行
private static void handleCallback(Message message) {
        message.callback.run();
    }

 结论:

 

posted on 2019-10-09 16:22  kenny.wmh  阅读(77)  评论(0)    收藏  举报

导航