Android-Handler源码解析-Handler

Android-Handler源码解析-Handler

成员变量

// 是否发现(检查)潜在的泄漏
private static final boolean FIND_POTENTIAL_LEAKS = false;
// Log的Tag
private static final String TAG = "Handler";
// 主线程Handler
private static Handler MAIN_THREAD_HANDLER = null;

// 此Handler的Looper
@UnsupportedAppUsage 
final Looper mLooper;

// 此Handler的消息队列,来自Looper对象。
final MessageQueue mQueue;

// 此Handler分发消息时,优先处理消息的Callback。
@UnsupportedAppUsage
final Callback mCallback;

// 是否是异步Handler,即是否send或post的消息全部都是异步消息,默认为false。
final boolean mAsynchronous;

// 跨进程通信,消息发送者。
@UnsupportedAppUsage
IMessenger mMessenger;
复制代码

说明:

  1. Handler为什么需要持有LooperMessageQueue,因为Handler发送消息等操作需要知道发送到哪个MessageQueue,而MessageQueue需要从Looper中获取,以便发出的消息能进行轮询分发
  2. Looper相关介绍,请看三方库-Handler源码解析-Looper
  3. MessageQueue相关介绍,请看三方库-Handler源码解析-MessageQueue

创建Handler

想要使用Handler,首先要创建Handler,所以我们接下来看下它是如何被创建的。

new Handler()

默认Looper

Handler()

@Deprecated
public Handler() {
    this(null, false);
}
复制代码

Handler(Callback)

@Deprecated
public Handler(@Nullable Callback callback) {
    this(callback, false);
}
复制代码

Handler(Callback, boolean)

/** @hide */
public Handler(@Nullable 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) {
            // 匿名类、成员类、局部类,并且不是静态的,警告提示(以下Handler类应该是静态的,否则可能会发生泄漏)。
            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                klass.getCanonicalName());
        }
    }

	// 获取当前线程的Looper
    mLooper = Looper.myLooper();
    if (mLooper == null) {
	    // 当前线程没有Looper,则抛出异常提示(不能在没有调用Looper.prepare()的线程中创建handler)。
        throw new RuntimeException(
            "Can't create handler inside thread " + Thread.currentThread()
                    + " that has not called Looper.prepare()");
    }
    // 获取Looper的消息队列
    mQueue = mLooper.mQueue;
    // 记录CallBack
    mCallback = callback;
    // 记录是否是异步的
    mAsynchronous = async;
}
复制代码

以上构造方法,使用默认Looper当前线程Looper)。如果这个线程没有looper,则抛出异常

说明:

  1. Handler()Handler(Callback)两个构造方法已经被标记@Deprecated(过时),因为在Handler构造过程中隐式选择一个Looper可能会导致错误,其中操作会自动丢失(如果Handler不需要新任务并退出)、崩溃(如果handler有时是在一个没有激活Looper线程创建的),或者竞态条件,其中handler关联的线程与作者预期的不符。相反,可以使用java.util.concurrent.Executor,或者使用Looper.getMainLooper,{link android.view.View#getHandler}或类似工具显式指定Looper。如果为了兼容性需要隐藏thread local行为,则使用new Handler(Looper.myLooper())让读者更清楚。
  2. Handler(Callback, boolean)两个构造方法已经被标记为@hide(隐藏),只能系统内部使用。
  3. 使用默认Looper当前线程Looper),如果这个线程没有looper,则抛出异常
  4. 参数Callback,为此Handler分发消息时,优先处理消息的Callback,详细见后面-分发Message
  5. 参数async,为此Handler发送消息时,是否全部发送异步/同步(默认同步)消息,详细见后面-发送Message
  6. 异步消息表示不需要同步消息进行全局排序中断事件异步消息不受MessageQueue.postSyncBarrier(long)引入的同步屏障的影响。
  7. MessageQueue同步屏障相关介绍,请看三方库-Handler源码解析-MessageQueue-同步屏障

指定Looper

Handler(Looper)

public Handler(@NonNull Looper looper) {
    this(looper, null, false);
}
复制代码

Handler(Looper, Callback)

public Handler(@NonNull Looper looper, @Nullable Callback callback) {
    this(looper, callback, false);
}
复制代码

Handler(Looper, Callback, boolean)

/** @hide */
@UnsupportedAppUsage
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}
复制代码

以上构造方法,使用指定Looper不是默认Looper

说明:

  1. Handler(Looper)Handler(Looper, Callback)两个构造方法未被标记@Deprecated(过时),并使用指定Looper推荐使用。
  2. Handler(Looper, Callback, boolean)构造方法已经被标记为@hide(隐藏),只能系统内部使用。

Handler.createAsync()

Handler.createAsync(Looper)

@NonNull
public static Handler createAsync(@NonNull Looper looper) {
    if (looper == null) throw new NullPointerException("looper must not be null");
    return new Handler(looper, null, true);
}
复制代码

Handler.createAsync(Looper, Callback)

@NonNull
public static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback) {
    if (looper == null) throw new NullPointerException("looper must not be null");
    if (callback == null) throw new NullPointerException("callback must not be null");
    return new Handler(looper, callback, true);
}
复制代码

Handler.createAsync()方法,为静态方法,创建一个异步Handler,其发布Message不受同步障碍(如显示vsync)的影响。

说明:

  1. 发送到异步handler的消息可以保证彼此之间的顺序,但不一定要按照来自其他Handlers的消息进行排序。

小结

  1. 创建-同步Handler,分为未指定Looper指定Looper两种方式创建
  • 未指定Looper,则使用当前线程Looper不推荐使用。
  • 指定Looper推荐使用,构造方法为Handler(Looper)Handler(Looper, Callback)
  1. 创建-异步Handler,使用Handler.createAsync(Looper)Handler.createAsync(Looper, Callback)方法创建

创建Message

想要使用Message,可以通过Handler创建Message,所以我们接下来看下它是如何被创建的。

obtainMessage()

@NonNull
public final Message obtainMessage() {
    return Message.obtain(this);
}

@NonNull
public final Message obtainMessage(int what) {
    return Message.obtain(this, what);
}

@NonNull
public final Message obtainMessage(int what, @Nullable Object obj) {
    return Message.obtain(this, what, obj);
}

@NonNull
public final Message obtainMessage(int what, int arg1, int arg2) {
    return Message.obtain(this, what, arg1, arg2);
}

@NonNull
public final Message obtainMessage(int what, int arg1, int arg2, @Nullable Object obj) {
    return Message.obtain(this, what, arg1, arg2, obj);
}
复制代码

以上obtainMessage()方法 ,从全局消息池返回一个新的消息。内部使用Message.obtain()方法创建消息,并将其Messagetarget为当前Handler

说明:

  1. Message.obtain()相关介绍,请看三方库-Handler源码解析-Message-创建Message

小结

  1. handler.obtainMessage()方法,使用Message.obtain()方法创建消息,并将其Messagetarget为当前Handler

发送Message

Message创建好后,便可以发送消息了,Handler除了可以通过sendMessage()方法发送消息,还可以通过post()方法执行指定Callback任务,所以我们接下来看下它们是如何被发送的。

send-Message

sendMessage()

public final boolean sendMessage(@NonNull Message msg) {
    return sendMessageDelayed(msg, 0);
}
复制代码

sendEmptyMessage()

public final boolean sendEmptyMessage(int what) {
    return sendEmptyMessageDelayed(what, 0);
}
复制代码

sendEmptyMessageDelayed()

public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageDelayed(msg, delayMillis);
}
复制代码

sendEmptyMessageAtTime()

public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageAtTime(msg, uptimeMillis);
}
复制代码

sendMessageDelayed()

public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
复制代码

sendMessageAtTime()

public boolean sendMessageAtTime(@NonNull 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);
}
复制代码

sendMessageAtFrontOfQueue()

public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
    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, 0);
}
复制代码

以上方法,为发送立即消息发送延迟消息发送指定时间消息将消息排在消息队列的前面

说明:

  1. sendMessage()sendEmptyMessage()发送立即消息消息,sendMessageDelayed()sendEmptyMessageDelayed()发送延迟消息消息,sendMessageAtTime()发送指定时间消息sendMessageAtFrontOfQueue()将消息排在消息队列的前面
  2. sendMessageAtFrontOfQueue(),为将消息排在消息队列的前面,以便在消息loop下一次迭代中处理。此方法仅用于非常特殊的情况——它很容易使消息队列挨饿导致排序问题产生其它意想不到的副作用
  3. 发送立即消息发送延迟消息指定时间发送将消息排在消息队列的前面,他们最终调用的都是enqueueMessage()方法。

我们接下来看下enqueueMessage()方法。

enqueueMessage()

private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
        long uptimeMillis) {
    // 指定Message的Handler为此Handler
    msg.target = this;
    msg.workSourceUid = ThreadLocalWorkSource.getUid();

	// 如果此Handler是异步的,则发送的所有消息都是异步的。
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    // 使用MessageQueue将消息加入到消息队列中
    return queue.enqueueMessage(msg, uptimeMillis); 
}
复制代码

enqueueMessage()方法,为将Message加入到MessageQueue中。

说明:

  1. 指定MessagetargetHandler,使MessageHandler关联,以便使用Handler处理Message
  2. 如果此Handler异步的,则发送的所有消息都是异步的。
  3. uptimeMillis参数为消息执行时刻立即执行的为SystemClock.uptimeMillis()延时执行的为SystemClock.uptimeMillis() + delayMillis指定时间发送的为指定的将消息排在消息队列的前面的为0
  4. MessageQueue加入消息相关介绍,请看三方库-Handler源码解析-MessageQueue-加入Message

post-Callback

post()

public final boolean post(@NonNull Runnable r) {
   return  sendMessageDelayed(getPostMessage(r), 0);
}
复制代码

postAtTime()

public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
    return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}

public final boolean postAtTime(@NonNull Runnable r, @Nullable Object token, long uptimeMillis) {
    return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}

复制代码

postDelayed()

public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {
    return sendMessageDelayed(getPostMessage(r), delayMillis);
}

public final boolean postDelayed(@NonNull Runnable r, @Nullable Object token, long delayMillis) {
    return sendMessageDelayed(getPostMessage(r, token), delayMillis);
}
复制代码

postAtFrontOfQueue()

public final boolean postAtFrontOfQueue(@NonNull Runnable r) {
    return sendMessageAtFrontOfQueue(getPostMessage(r));
}
复制代码

以上方法,为执行指定Callback任务,由Runnable实现。底层也是通过getPostMessage()方法将Runnable包装Message然后调用对应发送消息的方法进行发送发送消息详细看上面的-send-Message

接下来我们来看一下getPostMessage()方法的实现。

getPostMessage()

private static Message getPostMessage(Runnable r) {
	// 使用复用获取新的Message
    Message m = Message.obtain();
	// 将Runnable保存到Message的callback中
    m.callback = r;
    return m;
}

@UnsupportedAppUsage
private static Message getPostMessage(Runnable r, Object token) {
    Message m = Message.obtain();
    m.obj = token;
    m.callback = r;
    return m;
}
复制代码

getPostMessage()方法,使用复用机制获取新的Message,并将Runnable保存到Messagecallback中。

小结

  1. 发送消息分为send-Messagepost-Callbackpost-Callback底层也是通过send-Message进行发送(将Runnable保存到Messagecallback中)。
  2. 通过handler发送的消息,最终都会将MessageHandler关联,以便使用Handler处理Message
  3. 如果此Handler异步的,则发送的所有消息都是异步的。

分发Message

Looper.loop()方法开启后,并且此LooperMessageQueuenext()方法返回一个Message后,会调用HandlerdispatchMessage()方法,代码如下。

Loop->loopOnce()

private static boolean loopOnce(final Looper me,
            final long ident, final int thresholdOverride) {
        Message msg = me.mQueue.next(); // might block
        ...
        // 调用Handler分发消息
        msg.target.dispatchMessage(msg);
        ...
    }
复制代码

接下来我们来看一下HandlerdispatchMessage()方法。

dispatchMessage()

Handler->dispatchMessage()

public void dispatchMessage(@NonNull Message msg) {
    if (msg.callback != null) {
	    // 处理Callback
        handleCallback(msg);
    } else {
  	    // 处理Message
        if (mCallback != null) {
	        // handler的Callback不为空,优先它处理。
            if (mCallback.handleMessage(msg)) {
	            // 返回true,表示handler的Callback已经处理,不再需要handleMessage()方法处理。
                return;
            }
        }
        // 使用handleMessage方法处理
        handleMessage(msg);
    }
}
复制代码

dispatchMessage()方法,为分发消息,分为处理Callback处理Message,而的处理Message优先handlerCallback处理,其次再handleMessage()方法处理

说明:

  1. dispatchMessage()方法为public并且不是final,所以可以被覆写,一般不覆写此方法。

接下来我们先来看一下处理CallbackhandleCallback()方法。

handleCallback()

private static void handleCallback(Message message) {
	// 调用callback.run()方法(即runnable.run()方法)执行
    message.callback.run();
}
复制代码

handleCallback()方法,直接调用messagecallback(即Runnable)的run()方法执行

接下来我们再来看一下优先处理MessageHandler.Callback类,其次再来看一下其次处理handleMessage()方法。

Handler.Callback类

public interface Callback {
    /**
     * @return 如果不需要进一步处理,则为True。
     */
    boolean handleMessage(@NonNull Message msg);
}
复制代码

如果handler.mCallback有设置值,则优先它来处理,并且handleMessage()方法返回true,则不再需要handleMessage()方法处理。

handleMessage()

public void handleMessage(@NonNull Message msg) {
}
复制代码

handleMessage()方法,为处理消息,我们可以通过Messagewhat的值来区分,来实现自己的逻辑。

说明:

  1. handleMessage()方法为public并且不是final,所以可以被覆写,一般覆写此方法。

小结

  1. 分发Message,它是通过HandlerdispatchMessage()方法进行分发处理
  2. 分发Message,它分为处理Callback处理Message

2.1.处理Callback,直接调用callback(即Runnable)的run()方法执行。 2.2.处理Message优先handlerCallback处理,其次再handleMessage()方法处理。 3. dispatchMessage()handleMessage()方法均可以被覆写,一般只覆写handleMessage()方法即可。

移除Messages、Callbacks

removeMessages()

public final void removeMessages(int what) {
    mQueue.removeMessages(this, what, null);
}

public final void removeMessages(int what, @Nullable Object object) {
    mQueue.removeMessages(this, what, object);
}
复制代码

removeCallbacks()

public final void removeCallbacks(@NonNull Runnable r) {
    mQueue.removeMessages(this, r, null);
}

public final void removeCallbacks(@NonNull Runnable r, @Nullable Object token) {
    mQueue.removeMessages(this, r, token);
}
复制代码

removeCallbacksAndMessages()

public final void removeCallbacksAndMessages(@Nullable Object token) {
    mQueue.removeCallbacksAndMessages(this, token);
}
复制代码

以上方法,为移除指定whatMessage或指定runnableCallbacks,全部都是通过调用MessageQueueremoveXX方法进行移除

说明:

  1. MessageQueue移除消息相关介绍,请看三方库-Handler源码解析-MessageQueue-移除Message

小结

是否有Messages、Callbacks

hasMessages()

public final boolean hasMessages(int what) {
    return mQueue.hasMessages(this, what, null);
}
复制代码

hasCallbacks()

public final boolean hasCallbacks(@NonNull Runnable r) {
    return mQueue.hasMessages(this, r, null);
}
复制代码

hasMessagesOrCallbacks()

public final boolean hasMessagesOrCallbacks() {
    return mQueue.hasMessages(this);
}
复制代码

以上方法,为判断是否有指定whatMessage或指定runnableCallbacks,全部都是通过调用MessageQueuehasMessages方法进行判断

说明:

  1. MessageQueue是否有消息相关介绍,请看三方库-Handler源码解析-MessageQueue-是否有Message

小结

其它

getMessageName()

public String getMessageName(@NonNull Message message) {
    if (message.callback != null) {
	    // 是Callback类型,返回此Callback(即Runnable)的类名。
        return message.callback.getClass().getName();
    }
	// 是Message类型,返回此Message的what的十六进制。
    return "0x" + Integer.toHexString(message.what);
}
复制代码

获取表示指定Message名称字符串默认实现,是Callback类型返回此Callback(即Runnable)的类名,是Message类型返回此Messagewhat十六进制

getLooper()

@NonNull
public final Looper getLooper() {
    return mLooper;
}
复制代码

获取HandlerLooper对象

dump()

public final void dump(@NonNull Printer pw, @NonNull String prefix) {
    pw.println(prefix + this + " @ " + SystemClock.uptimeMillis());
    if (mLooper == null) {
        pw.println(prefix + "looper uninitialized");
    } else {
        mLooper.dump(pw, prefix + "  ");
    }
}
复制代码

转储looper的状态,以进行调试。如果Looper为空,直接打印,否则调用Looperdump()方法。

说明:

  1. Looperdump的相关介绍,请看Looper-其它

猜你喜欢

转载自juejin.im/post/7085976728538972190