Android Handler消息机制

2020-08-22  本文已影响0人  啊噜啊噜

1、简介

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

2、Handler消息机制的作用

两个主要作用:

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;
                }


            }
        //省略代码
        }
    }
上一篇 下一篇

猜你喜欢

热点阅读