View Post使用過程需要注意的問題

問題:

流程:在ImageLoader中,在item create的時候,就利用 view.post 方式請求加載 placeholder Runnable,圖片加載完成之後,再在Thread線程中 通過View.post 方式請求加載Image Runnable。

 

現象:

會出現 概率性Image加載不出來的。

 

直接原因:

發現是 兩次post,第一次先執行的是 Image 的Runnable,然後再執行的placeholder Runnable。

 

6.0版本View.post代碼:

public boolean post(Runnable action) {

final AttachInfo attachInfo = mAttachInfo;

if (attachInfo != null) {

return attachInfo.mHandler.post(action);

}

// Assume that post will succeed later

ViewRootImpl.getRunQueue().post(action);

return true;

}

 

分析:

1.按照代碼邏輯,首先是 View.post placeholder Runnable,然後再去執行的 View.post Image Runnable,這是合乎邏輯的;

(懷疑過 Handler被堵塞..........甚至懷疑過 View.post 執行的順序。)

2.查詢Android版本(因爲在 7.0 8.0 都是正常的),發現 6.0版本的View.post和7.0 、8.0的機制有一點不一樣導致:

相同點:在view 沒有Attached狀態的時,6.0和7.0的View.post 都是放到RunQueue裏面去的。

不同點:6.0的post的Runnable任務在心跳到來的時候,執行ViewRootImpl.performTraversals的時候會去通過Handler.post把任務放到MessageQueue中,等待Looper來取出並交給Handler執行。

 

3.發現問題點就出現 在,

3.1 第一次view.post placeholder Runnable的時候,view 還沒進入Attached 狀態,所以attachInfo 是null,於是 Runnable放入了 RunQueue中;

3.2 第二次view.post Image Runnable的時候,attachInfo不爲null ,直接交給Handler來處理;

3.3 因爲RunQueue的任務執行的時機是 心跳到來的時刻,這個時間正好晚於 Image Runnale放進MessageQueue的時刻,導致Placeholder Runnable排在Image Runnable後面;

 

4.至於在7.0、8.0是OK的原因,是因爲這些版本的view.post 的任務,是在view 進入Attached 狀態之後纔會被執行,這個時候正好 Image Runnable放入Handler的時機比較湊巧的晚於Placeholder Runnable;

void dispatchAttachedToWindow(AttachInfo info, int visibility) {

mAttachInfo = info;

...

// Transfer all pending runnables.

if (mRunQueue != null) {

mRunQueue.executeActions(info.mHandler);

mRunQueue = null;

}

.....

}

 

總結:

儘量使用Handler吧,如果沒特別的需求的話;

 

說實話,以前特麼還真麼注意這些細節,另外,Android 版本太碎片化導致我們的工作量陡增.....

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