IdleHandler的使用和源碼解析

1.作用

IdleHandler用於執行耗時較短且非必須的任務,它會在消息隊列空閒時執行任務,可以用於性能優化。

2.使用

 

queueIdle函數返回false的話,這個任務會被執行一次,如果返回true,則消息隊列空閒時就執行(注意不是隻要空閒了就不斷執行,而且空閒後就執行一次)

 

    var handler:MessageQueue.IdleHandler = object :MessageQueue.IdleHandler{
        override fun queueIdle(): Boolean {
            Log.v("zzw","queueIdle")
            return true
        }
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mainLooper.queue.addIdleHandler(handler)
        }
    }

3.源碼分析

 首先從MessageQueue 添加 IdleHandler 開始看

    public void addIdleHandler(@NonNull IdleHandler handler) {
        synchronized (this) {
            mIdleHandlers.add(handler);
        }
    }

然後 再找mIdleHandlers哪裏被調用了,在next中找到了,以下是簡化代碼


    @UnsupportedAppUsage
    Message next() {

        for (;;) {


            synchronized (this) {


//看消息隊列裏是否有到時間,需要執行的Message,如果有就return,沒有就繼續


//判斷mIdleHandlers是否爲空,若爲空則跳過

                
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }

//初始化mPendingIdleHandlers 
                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
//將mIdleHandlers的前四個數據給它,
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }

//循環執行mPendingIdleHandlers 數組的每個元素
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler

                boolean keep = false;
                try {
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }

//如果queueIdle返回false,則執行完就移除
                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }


        }
    }

next函數雖然裏面是一個無限循環,對於 queueIdle返回 true的情況,看起來是要無限循環執行queueIdle函數的,但是之所以會停,因爲Looper在消息隊列爲空,且IdleHandler數組 執行完或沒有的情況,會休眠,在收到消息 之後纔會重新開始運行,遍歷消息隊列,然後執行IdleHandler數組

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章