MessageQueue内部有个IdleHandler接口,具体定义如下:
/** * Callback interface for discovering when a thread is going to block * waiting for more messages. */ public static interface IdleHandler { /** * Called when the message queue has run out of messages and will now * wait for more. Return true to keep your idle handler active, false * to have it removed. This may be called if there are still messages * pending in the queue, but they are all scheduled to be dispatched * after the current time. */ boolean queueIdle(); }
简而言之,就是在looper里面的message暂时处理完了,这个时候会回调这个接口,返回false,那么就会移除它,返回true就会在下次message处理完了的时候继续回调。
下面先通过个例子来直观看下IdleHandler的执行时机。
public class IdleHandleActivity extends Activity { public static final String TAG = "IdleHandleActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "onCreate"); setContentView(R.layout.activity_idle_handler); Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() { @Override public boolean queueIdle() { Log.d(TAG, "IdleHandler post"); return false; } }); new Handler().post(new Runnable() { @Override public void run() { Log.d(TAG, "Handler post1"); } }); new Handler().post(new Runnable() { @Override public void run() { Log.d(TAG, "Handler post2"); } }); new Handler().postDelayed(new Runnable() { @Override public void run() { Log.d(TAG, "Handler delay post"); } }, 500); } @Override protected void onStart() { super.onStart(); Log.d(TAG, "onStart"); } @Override protected void onResume() { super.onResume(); Log.d(TAG, "onResume"); } }
public class MyView extends TextView { ...... @Override protected void onFinishInflate() { super.onFinishInflate(); Log.d(IdleHandleActivity.TAG, getText() + " onFinishInflate"); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.d(IdleHandleActivity.TAG, getText() + " onMeasure"); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); Log.d(IdleHandleActivity.TAG, getText() + " onLayout"); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.d(IdleHandleActivity.TAG, getText() + " onDraw"); } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.outman.example.androidtest.MainActivity"> <com.outman.example.androidtest.MyView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="MyView!"/> </LinearLayout>
执行结果:
04-08 17:30:33.994 16452-16452/ D/IdleHandleActivity: onCreate 04-08 17:30:34.038 16452-16452/ D/IdleHandleActivity: MyView! onFinishInflate 04-08 17:30:34.068 16452-16452/ D/IdleHandleActivity: onStart 04-08 17:30:34.073 16452-16452/ D/IdleHandleActivity: onResume 04-08 17:30:34.089 16452-16452/ D/IdleHandleActivity: Handler post1 04-08 17:30:34.089 16452-16452/ D/IdleHandleActivity: Handler post2 04-08 17:30:34.097 16452-16452/ D/IdleHandleActivity: MyView! onMeasure 04-08 17:30:34.106 16452-16452/ D/IdleHandleActivity: MyView! onMeasure 04-08 17:30:34.107 16452-16452/ D/IdleHandleActivity: MyView! onLayout 04-08 17:30:34.125 16452-16452/ D/IdleHandleActivity: MyView! onDraw 04-08 17:30:34.136 16452-16452/ D/IdleHandleActivity: IdleHandler post 04-08 17:30:34.569 16452-16452/ D/IdleHandleActivity: Handler delay post
通过执行结果可以看到
1. IdleHandler的回调在,所有Handler执行完MessageQueue中的内容,再执行
2. IdleHandler的回调在,Activity执行完onResume方法,再执行
3. IdleHandler的回调在,初始化完View后,即执行完onDraw后,再执行
在Glide和LeakCanary中都有IdleHandler的使用
Glide中
// Responsible for cleaning up the active resource map by remove weak references that have been cleared. private static class RefQueueIdleHandler implements MessageQueue.IdleHandler { private final Map<Key, WeakReference<EngineResource<?>>> activeResources; private final ReferenceQueue<EngineResource<?>> queue; public RefQueueIdleHandler(Map<Key, WeakReference<EngineResource<?>>> activeResources, ReferenceQueue<EngineResource<?>> queue) { this.activeResources = activeResources; this.queue = queue; } @Override public boolean queueIdle() { ResourceWeakReference ref = (ResourceWeakReference) queue.poll(); if (ref != null) { activeResources.remove(ref.key); } return true; } }
LeakCanary中
private void showToast(final FutureResult<Toast> waitingForToast) { mainHandler.post(new Runnable() { @Override public void run() { final Toast toast = new Toast(context); toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0); toast.setDuration(Toast.LENGTH_LONG); LayoutInflater inflater = LayoutInflater.from(context); toast.setView(inflater.inflate(R.layout.leak_canary_heap_dump_toast, null)); toast.show(); // Waiting for Idle to make sure Toast gets rendered. Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() { @Override public boolean queueIdle() { waitingForToast.set(toast); return false; } }); } }); }
参考 https://mp.weixin.qq.com/s/KpeBqIEYeOzt_frANoGuSg