安卓handler机制

一个人想着一个人 提交于 2019-12-27 15:24:34

sendMessage方式:根据以上表格中三个关键类,下面分别从源码角度解释其作用

步骤:

1.Handler(创建handler对象时,主要做了两件事,1.指定looper对象;2.指定messageQueue对象)


//流程:创建handler对象——>Handler构造方法——>指定当前线程的looper对象
=绑定当前线程——>指定looper对象中保存的消息队列对象MessageQueue



/** 
  * a.使用
  */
    private Handler mhandler = new  Handler(){
        // 通过复写handlerMessage()从而确定更新UI的操作
        @Override
        public void handleMessage(Message msg) {
                ...// 需执行的UI操作
            }
    };

/**
  *b.源码
  */

  public Handler(Callback callback, boolean async) {

            // 1. 指定Looper对象
                mLooper = Looper.myLooper();
                if (mLooper == null) {
                    throw new RuntimeException(
                        "Can't create handler inside thread that has not called Looper.prepare()");
                }


            // 2. 绑定MessageQueue
                mQueue = mLooper.mQueue;

    }



 

2.Looper类(主要看两个核心方法,1.looper.prepare(),在activityThread中的静态Main方法中为主线程创建looper对象和messageQueue对象;2.Looper.loop:不断地循环地从消息队列中取出message,无消息时则阻塞)  


public static void loop() {
        
        ...// 仅贴出关键代码

            final Looper me = myLooper();
            if (me == null) {
                throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
            }
            // myLooper()作用:返回sThreadLocal存储的Looper实例;若me为null 则抛出异常

            final MessageQueue queue = me.mQueue;

        // 2. 消息循环(通过for循环)
            for (;;) {
            
            Message msg = queue.next(); 
            if (msg == null) {
                return;
            }
            // 若取出的消息为空,则线程阻塞

            msg.target.dispatchMessage(msg);
            // 把消息Message派发给消息对象msg的target属性
            // target属性实际是1个handler对象

        // 3. 释放消息占据的资源
        msg.recycle();
        }
}

 

 3.MessageQueue(本质上是个链表,主要有两个方法,存和取。1.存:enqueueMessage;2.取:next)   

/** a.enqueueMessadsge(放入消息)
          * 单链表:提高插入、删除消息的效率

          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()) {
                                    needWake = false;
                                }
                            }

                            msg.next = p; 
                            prev.next = msg;
                        }

                        if (needWake) {
                            nativeWake(mPtr);
                        }
                    }
                    return true;
            }

b.next(取出消息)

  Message next() {

        // 该参数用于确定消息队列中是否还有消息
        // 从而决定消息队列应处于出队消息状态 or 等待状态
        int nextPollTimeoutMillis = 0;

        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }

        // nativePollOnce方法在native层,若是nextPollTimeoutMillis为-1,此时消息队列处于等待状态 
        nativePollOnce(ptr, nextPollTimeoutMillis);

        synchronized (this) {
     
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;

            // 出队消息,即 从消息队列中取出消息:按创建Message对象的时间顺序
            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 {

                // 若 消息队列中已无消息,则将nextPollTimeoutMillis参数设为-1
                // 下次循环时,消息队列则处于等待状态
                nextPollTimeoutMillis = -1;
            }

            ......
        }
           .....
       }
}

总结:handler发送消息到消息队列中,调用messageQueue的enqueueMessage方法将消息入队,再通过next方法,looper不断循环从消息队列中取出消息,然后handler发送消息,最终由handleMessage处理消息。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!