Android 事件处理模型(三)消息传递机制: Handler Looper MessageQueue

最近的工作涉及了Android的Handler消息传递,总结如下:

1. Handler :

为了实现线程和Activity中widget之间的通信,比如为了进行某些耗时操作而新开的线程,在这些操作中如果要跟新UI则需要Handler来处理。它主要负责Message的分发和实现不同Message操作的自定义,相当于句柄。

2. MessageQuene:

Message是线程和widget通信的介质,也就是来传递信息的,显然MessageQuene则是保存Message的列表,在代码中表现为ArrayList。

3. Looper:

是一个控制器,它不断的从MessageQuene中取Message,然后将Message传递给Handler中的handleMessage方法以实现用户自定义操作。


一个线程只能有一个Looper,线程中可能有多个Handler,一个Looper管理一个MessageQuene,不同线程的Looper由ThreadLocal管理。


整个工作流程如下:

1. 线程工作流程

线程注册Looper =>

线程注册Handler=>

Handler sendMessage 到 MessageQuene 


 2. Looper工作流程

在Looper.prepare()中Looper被注册 =>

Looper执行Looper.loop() 取MessageQuene中的Message,执行Message的Handler(句柄)的handlerMessage方法,实现自定义操作。 =>

Looper的管理通过ThreadLocal类实现,ThreadLocal机制:为不同线程管理变量副本,实现多线程异步操作。


源码分析如下:

 1. 调用流程

public class HelloAndroidActivity extends Activity {
    Handler handler = new Handler() {//根据返回Message自定义操作
        public void handleMessage(Message msg) {
        ......
        }
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Thread thread = new Thread() {
            public void run() {
                Looper.prepare();//注册Looper
                ........
                Looper.loop();//Looper开始操作MessageQuene
                handler.sendMessage(new Message());//发送消息到MessageQuene
            }
        };
        thread.start();//启动线程
    }
}

2. 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 the thread /
 * message queue of the thread that is creating it -- from that point on,
 * it will deliver messages and runnables to that message queue and execute
 * them as they come out of the message queue.
 */
public class Handler {
    /**
     * Subclasses must implement this to receive messages.
     */
    public void handleMessage(Message msg) {
    }
    /** 初始化handler,确认Handler的mLooper, mQueue,callback等等
     * Use the {@link Looper} for the current thread with the specified callback interface
     * and set whether the handler should be asynchronous.
     *
     * Handlers are synchronous by default unless this constructor is used to make
     * one that is strictly asynchronous.
     *
     * Asynchronous messages represent interrupts or events that do not require global ordering
     * with represent to synchronous messages.  Asynchronous messages are not subject to
     * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
     *
     * @param callback The callback interface in which to handle messages, or null.
     * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
     * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
     *
     * @hide
     */
    public Handler(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 that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    } /** * Handle system messages here. */在Looper.loop()中会调用这个函数,实现handle message public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } /** * Default constructor associates this handler with the queue for the * current thread. * * If there isn't one, this handler won't be able to receive messages. */ public Handler() { mLooper = Looper.myLooper();//获取该线程Looper if (mLooper == null) {//确保该线程已注册Looper throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = null; } /** * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this). * If you don't want that facility, just call Message.obtain() instead. */获取消息,比new效率高 public final Message obtainMessage() { return Message.obtain(this); } /** * Causes the Runnable r to be added to the message queue. * The runnable will be run on the thread to which this handler is * attached. * * @param r The Runnable that will be executed. * * @return Returns true if the Runnable was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } /** * Pushes a message onto the end of the message queue after all pending messages * before the current time. It will be received in {@link #handleMessage}, * in the thread attached to this handler. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */网MessageQuene中加入消息 public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } /** * Remove any pending posts of messages with code 'what' that are in the * message queue. */ public final void removeMessages(int what) { mQueue.removeMessages(this, what, null, true); }}

3. Looper分析

/**
 * Class used to run a message loop for a thread.  Threads by default do
 * not have a message loop associated with them; to create one, call
 * {@link #prepare} in the thread that is to run the loop, and then
 * {@link #loop} to have it process messages until the loop is stopped.
 */
public class Looper {
    Thread mThread;
    private static Looper mMainLooper = null;

    /** Initialize the current thread as a looper.
     * This gives you a chance to create handlers that then reference
     * this looper, before actually starting the loop. Be sure to call
     * {@link #loop()} after calling this method, and end it by calling
     * {@link #quit()}.
     * 为进程注册Looper,并确保每个进程一个Looper,
     * ThreadLocal为不同进程分别管理相应Looper
     */
    public static final void prepare() {
       if (sThreadLocal.get() != null) {
           throw new RuntimeException("Only one Looper may be created per thread");
       }
       sThreadLocal.set(new Looper());
    }

    /**
     *  Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     * 不停的取message,并调用其Handler.
     */
    public static final void loop() {
        Looper me = myLooper();
        MessageQueue queue = me.mQueue;

        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        while (true) {
            Message msg = queue.next(); // might block
            //if (!me.mRun) {
            //    break;
            //}
            if (msg != null) {
                if (msg.target == null) {
                    // No target is a magic identifier for the quit message.
                    return;
                }
                if (me.mLogging!= null) me.mLogging.println(
                        ">>>>> Dispatching to " + msg.target + " "
                        + msg.callback + ": " + msg.what
                        );
                msg.target.dispatchMessage(msg);
                if (me.mLogging!= null) me.mLogging.println(
                        "<<<<< Finished to    " + msg.target + " "
                        + msg.callback);

                // Make sure that during the course of dispatching the
                // identity of the thread wasn't corrupted.
                final long newIdent = Binder.clearCallingIdentity();

                msg.recycle();
            }
        }
    }
    
    /**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     * 获取当前线程Looper
     */
    public static final Looper myLooper() {
        return (Looper)sThreadLocal.get();
    }
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值