Android相关

Android『消息传递』

2019-04-10  本文已影响0人  cname_1

Hanlder构造方法

在创建Handler时,Handler在其构造方法中尝试从当前线程(创建Hanlder实例对象的线程)的ThreadLocal中取到Looper对象,并将该Looper对象赋值给当前Hanlder对象,同时还会将Looper对象的MessageQueue引用赋值给当前Handler。

//Lopper.myLooper
public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}
//new Handler()
public Handler(Callback callback, boolean async) {
        ...
    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;
}

Looper.prepare()

在子线程中尝试创建Handler对象时,检测当前线程是否已经关联Looper对象,不存在就报错(需要调用Looper.prepare()进行关联),存在的话直接返回当前线程关联的Looper对象,使Handler持有Looper和Looper.MessageQueue的引用,从而能够往MessageQueue中添加消息。一个线程最多只能创建一个Looper,但是多个Handler可以对应同一个Looper,只要在一个线程中。

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

在主线程中创建Handler不需要手动调用Looper.prepare(),因为主线程的ActivityThread变量在main方法中调用了prepareMainLooper()来初始化了主线程的Looper对象。

//ActivityThread.main()
public static void main(String[] args) {
    ...

    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    if (false) {
        Looper.myLooper().setMessageLogging(new
            LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    Looper.loop();
}

sendMessage()和sendMessageAtTime()

Handler的sendMessage调用的是MessageQueue.enqueueMessage(Message,uptimeMillis),因为可能存在多个线程同时往同一个MessageQueue中插入Message,所以MessageQueue.enqueueMessage是同步方法sendMessage()最终调用sendMessageAtTime(),只不过它的uptimeMillis参数为0,即不延时执行的意思。

//Handler.sendMessage() 
public final boolean sendMessage(Message msg) {
    return sendMessageDelayed(msg, 0);
}
//Hanlder.sendMessageDelayed
public final boolean sendMessageDelayed(Message msg, long delayMillis){
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

这里的uptimeMillis随Msg存入到MQ,而sendMessageDelayed()的延迟执行效果是有MQ在取出消息进行dispatch时完成的,取出消息时会比对当前时间和Msg的when属性。

//Handler.sendMessageAtTime()
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis);
}
//Handler.enqueueMessage()
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}
//MessageQueue.enqueueMessage()
boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }

        synchronized (this) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                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; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

Looper.loop()

Looper调用loop()方法,其中不断从MessageQueue中取出Message(通过message.next()方法),进行dispatchMessage,其实在Handler调用sendMessage时已经将自己设置为Message.target了,所以dispatch只是将message发给自己的target处理而已

主线程如何通过Handler发送Message通信

定义一个全局的Handler对象mHandler;在子线程A中初始化这个mHandler,并重写handlerMessage()方法;在子线程B中调用mHandler.obtainMessage()方法从Message类自带的Message Pool中返回一个Message对象,然后使用message.sendToTarget()方法,发送消息。

主线程的Looper.loop()一直无限循环,为何没有ANR?

//Looper.loop()
public static void loop() {
    ...
    for (;;) {
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }
        ...
    }
    ...
}

首先需要知道造成ANR的原因:

  1. 当前的事件没有机会得到处理(即主线程正在处理前一个事件,没有及时的完成或者looper被某种原因阻塞住了)。
  2. 当前的事件正在处理,但没有及时完成。执行时间超过了ANR的阈值:按键事件 5s ,broadcast 10s、前台service无响应的超时时间为20秒,后台service为200秒。

这样就可以解释为什么主线程的Looper.loop()一直无限循环但是为什么没有造成ANR了,从上面的代码可以看出当没有Message需要处理时,主线程没有进行任何和造成ANR有关的事件的处理,虽然是在无限循环,但是比起频繁的开启、关闭消息循环动作,这样的开销反而更小吧。

转载请注明出处:https://www.jianshu.com/writer#/notebooks/14980289/notes/44701526/preview

上一篇下一篇

猜你喜欢

热点阅读