android的MessageQueue.IdleHandler

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

 

    原文作者:移动开发
    原文地址: https://my.oschina.net/android520/blog/1791335
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞