消息处理机制

相关类

  • Message:消息,其中包含了消息ID,处理对象和处理数据,由MessageQueue统一队列管理,最终由Handler处理。
  • Handler:负责Message发送和处理。
  • MessageQueue:消息队列,按照FIFO原则存放消息。
  • Looper:消息泵,来处理MessageQueue中的Message。
Message,MessageQueue,Handler,Looper之间的关系

看代码

Looper.class
变量
 /**
  * 用于管理Looper
  */
 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
 /**
  * 持有主线程Looper
  */
 private static Looper sMainLooper;  // guarded by Looper.class

 /**
  * 每个Looper持有一个消息队列
  */
 final MessageQueue mQueue;
 /**
  * 每个Looper持有一个线程
  */
 final Thread mThread;
方法
/**
 * 创建一个Looper
 */
public static void prepare() {
    prepare(true);
}

/**
 * 真实的创建Looper的方法
 * @param quitAllowed
 */
private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

/**
 * 初始化一个主线程的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();
    }
}

/**
 * 返回一个主线程的上的Looper
 */
public static Looper getMainLooper() {
    synchronized (Looper.class) {
        return sMainLooper;
    }
}

/**
 * 进行消息循环,获取消息,发送消息
 */
public static void loop() {
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;
    ......
    for (;;) {
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }
        msg.target.dispatchMessage(msg);
    ......

    }
}

/**
 * 返回一个当前线程中的Looper
 * @return
 */
public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

/**
 * 返回消息队列
 * @return
 */
public static @NonNull MessageQueue myQueue() {
    return myLooper().mQueue;
}

private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

/**
 * 判断当前线程是否和Looper的线程相同
 * @return
 */
public boolean isCurrentThread() {
    return Thread.currentThread() == mThread;
}
MessageQueue.class
/**
 * 消息入队列,按时顺序进行排序存储
 *
 * @param msg 消息实体
 * @param when 消息发送时间
 * @return
 */
boolean enqueueMessage(Message msg, long when) {
    ......
    synchronized (this) {

        .....
        msg.markInUse();
        msg.when = when;
        Message p = mMessages;
        boolean needWake;
        if (p == null || when == 0 || when < p.when) {
            /**
             * 把消息放到消息队列的头上,需要唤醒
             */
            msg.next = p;
            mMessages = msg;
            needWake = mBlocked;
        } else {
            /**
             * 把消息插入到合适的位置
             */
            needWake = mBlocked && p.target == null && msg.isAsynchronous();
            Message prev;
            for (;;) {
                prev = p;
                p = p.next;
                if (p == null || when < p.when) {
                    break;
                }
                if (needWake && p.isAsynchronous()) {
                //说明即便msg是异步的,也不是链表中第一个异步消息,所以没必要唤醒了
                    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;
}
/**
 *
 * 获取消息实体
 *
 * @return
 */
Message next() {
    // Return here if the message loop has already quit and been disposed.
    // This can happen if the application tries to restart a looper after quit
    // which is not supported.
    final long ptr = mPtr;
    if (ptr == 0) {
        return null;
    }

    int pendingIdleHandlerCount = -1; // -1 only during first iteration
    int nextPollTimeoutMillis = 0;
    for (;;) {
        if (nextPollTimeoutMillis != 0) {
            Binder.flushPendingCommands();
        }

        nativePollOnce(ptr, nextPollTimeoutMillis);

        synchronized (this) {
            // Try to retrieve the next message.  Return if found.
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;
            if (msg != null && msg.target == null) {
                // Stalled by a barrier.  Find the next asynchronous message in the queue.
                do {
                    prevMsg = msg;
                    msg = msg.next;
                } while (msg != null && !msg.isAsynchronous());
            }
            if (msg != null) {
                /**
                 * 获取消息
                 */
                if (now < msg.when) {
                    /**
                     * 下一个消息还没有准备好需要等待
                     */
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    /**
                     * 获取下个消息
                     */
                    mBlocked = false;
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                    msg.markInUse();
                    return msg;
                }
            } else {
                // No more messages.
                /**
                 * 没有任何消息
                 */
                nextPollTimeoutMillis = -1;
            }

            // Process the quit message now that all pending messages have been handled.
            if (mQuitting) {
                dispose();
                return null;
            }
            ......
        }

        /**
         * 在空闲的时候进行调用
         */
        for (int i = 0; i < pendingIdleHandlerCount; i++) {
            final IdleHandler idler = mPendingIdleHandlers[i];
            mPendingIdleHandlers[i] = null; // release the reference to the handler

            boolean keep = false;
            try {
                keep = idler.queueIdle();
            } catch (Throwable t) {
                Log.wtf(TAG, "IdleHandler threw exception", t);
            }

            if (!keep) {
                synchronized (this) {
                    mIdleHandlers.remove(idler);
                }
            }
        }

        // Reset the idle handler count to 0 so we do not run them again.
        pendingIdleHandlerCount = 0;

        // While calling an idle handler, a new message could have been delivered
        // so go back and look again for a pending message without waiting.
        nextPollTimeoutMillis = 0;
    }
}

这里有个syncBarrier(同步分割栏)但是对其操作都是@hide,使用还还需要用java反射机制。 barrier的作用就是在某个时间阻拦不是异步的消息,如果需要继续获取消息必须把这个barrier给remove掉。

Message.class
/**
 * 消息实体的唯一标示
 */
public int what;

/**
 * 消息实体参数
 */
public int arg1;

/**
 * 消息实体参数
 */
public int arg2;

/**
 * 消息实体中的存储对象
 */
public Object obj;


/**
 * 发送时间
 */
/*package*/ long when;
/**
 * 消息实体中所带的数据
 */
/*package*/ Bundle data;

/**
 * 处理对象
 */
/*package*/ Handler target;

/**
 * 回调方法
 */
/*package*/ Runnable callback;


/**
 * 消息对象池
 */
private static Message sPool;
/**
 * 消息对象个数
 */
private static int sPoolSize = 0;

/**
 * 默认最大个数为50
 */
private static final int MAX_POOL_SIZE = 50;

Message不能通过new创建对象应该通过obtain方法获取Message对象,因为为了避免大量的创建Message对象,Message会通过自身维护的一个对象池取Message对象。

obtain方法

  • public static Message obtain()
  • public static Message obtain(Message orig)
  • public static Message obtain(Handler h)
  • public static Message obtain(Handler h, Runnable callback)
  • public static Message obtain(Handler h, int what)
  • public static Message obtain(Handler h, int what, Object obj)
  • public static Message obtain(Handler h, int what, int arg1, int arg2)
  • public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj)

设置处理者

  • public void setTarget(Handler target)

发送消息给处理者

  • public void sendToTarget()

处理捆绑数据

  • public Bundle getData()
  • public Bundle peekData()
  • public void setData(Bundle data)
Handler.class
/**
 * 处理消息接口
 */
public interface Callback {
    public boolean handleMessage(Message msg);
}

/**
 * 实现这个方法处理消息
 */
public void handleMessage(Message msg) {
}

/**
 * 这个是当mssage.callback不会空的时候执行
 * @param message
 */
private static void handleCallback(Message message) {
    message.callback.run();
}

/**
 * 由Looper在获取消息后调用,这里是处理消息的逻辑
 */
public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        /**
         * 如果message中没有callback函数,就直接执行handler中的静态方法handleMessage
         */
        handleCallback(msg);
    } else {
        /**
         * 如果Handler中定义了mCallback,那么先去执行mCallBack中的内容。
         * 如果mCallback返回true,说明被mCallback中的handleMessage处理完成不在需要后续的Handler中的handleMessage处理
         * 如果mCallback返回false,说明mCallback中的handleMessage没有处理完消息,后续有Handler中的handleMessage继续处理
         */
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

这里有两个handleCallback,一个是静态的方法,一个是普通方法;在调用的时机不一样,静态方法是在Message中定义了callback的时候调用的。

相对应Message中获取Message对象的方法

  • public final Message obtainMessage()
  • public final Message obtainMessage(int what)
  • public final Message obtainMessage(int what, Object obj)
  • public final Message obtainMessage(int what, int arg1, int arg2)
  • public final Message obtainMessage(int what, int arg1, int arg2, Object obj)

用Runnable接收消息,这里的Runnable和线程中的Runable不一样只是一个普通的方法,运行在当前线程中。

  • public final boolean post(Runnable r)
  • public final boolean postAtTime(Runnable r, long uptimeMillis)
  • public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
  • public final boolean postDelayed(Runnable r, long delayMillis)
  • public final boolean postAtFrontOfQueue(Runnable r)

直接发送消息

  • public final boolean sendMessage(Message msg)
  • public final boolean sendEmptyMessage(int what)
  • public final boolean sendEmptyMessageDelayed(int what, long delayMillis)
  • public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis)
  • public final boolean sendMessageDelayed(Message msg, long delayMillis)
  • public boolean sendMessageAtTime(Message msg, long uptimeMillis)
  • public final boolean sendMessageAtFrontOfQueue(Message msg)

results matching ""

    No results matching ""