美文网首页
Android Handler消息机制

Android Handler消息机制

作者: 啊噜啊噜 | 来源:发表于2020-08-22 20:47 被阅读0次

    1、简介

    Android Handler消息机制由Handler、Looper、Message、MessageQueue组成。

    • Handler - 负责发送并处理Message
    • Message - 消息的承载体
    • MessageQueue 消息队列 - 存储Message对象
    • Looper 轮询器 - 不断从MessageQueue中去轮询是否有Message对象

    2、Handler消息机制的作用

    两个主要作用:

    • 调度Message或在某个时刻执行Runnable
    • 线程间的通信

    3、Looper与线程相关联

    下面以主线程的Looper为例

    ActivityThread

      public static void main(String[] args) {
           //省略代码
            //初始化主线程的Looper
            Looper.prepareMainLooper();
            //省略代码
          if (sMainThreadHandler == null) {//创建主线程的Handler
                sMainThreadHandler = thread.getHandler();
            }
    
            //开启Looper循环
            Looper.loop();
    
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }
    

    Looper

      public static void prepareMainLooper() {
            prepare(false);
            synchronized (Looper.class) {
                if (sMainLooper != null) {
                    throw new IllegalStateException("The main Looper has already been prepared.");
                }
              //创建主线程的Looper
                sMainLooper = myLooper();
            }
        }
    
     public static @Nullable Looper myLooper() {
            //通过ThreadLocal获取,ThreadLocal是线程的成员变量
            return sThreadLocal.get();
        }
    

    ThreadLocal

    public T get() {
            //获取当前的线程
            Thread t = Thread.currentThread();  
            //ThreadLocalMap也是Thread的成员变量
            //ThreadLocalMap是一个Map结构,以ThreadLocal为Key值。在这里Value的是Looper对象
            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();
        }
    

    总结:Looper通过调用myLooper()方法初始化Looper对象,Looper对象持有一个ThreadLocal对象,这个ThreadLocal存储了当前的Looper对象,然后把Looper对象持有的ThreadLocal对象存储到Thread的ThreadLocalMap中。

    4、Handler与线程相关联

    public Handler(@Nullable Callback callback, boolean async) {
           //省略代码
          //初始化Looper
            mLooper = Looper.myLooper();
            if (mLooper == null) {
                throw new RuntimeException(
                    "Can't create handler inside thread " + Thread.currentThread()
                            + " that has not called Looper.prepare()");
            }
            mQueue = mLooper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
        }
    

    总结:当Handler创建的时候,Handler持有Looper对象也会通过Looper.myLooper()方法进行初始化,从而使得Handler、Looper都关联到同一个线程。从上面我们也可以得知,为什么当在子线程中创建其所属的Handler时必须调用Looper.prepare()。在主线程不需要调用是因为在主线程启动的时候,系统以及为我们调用了相应的方法。

    5、Looper.loop()通过死循环开启轮询为什么不会ANR

    Android是事件驱动的Linux操作系统Looper.loop()不断的接收处理事件,Looper.loop() 一旦退出,应用程序的
    也就结束了。发生ANR使用事件没有得到处理或者事件正在处理,但是没有及时完成。另外当MessageQueue中没有消息时,会调用nativePollOnce()方法,主线程会释放CPU资源进入休眠状态,直到下条消息到达或者有事务发生,通过往pipe管道写端写入数据来唤醒主线程工作,采用的是epoll机制。

    Message next() {
           
            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();
                }
                //当没有Message时,进入该方法
                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) {
                            // Next message is not ready.  Set a timeout to wake up when it is ready.
                            nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                        } else {
                            // Got a message.
                            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;
                    }
    
    
                }
            //省略代码
            }
        }
    

    相关文章

      网友评论

          本文标题:Android Handler消息机制

          本文链接:https://www.haomeiwen.com/subject/vczvjktx.html