<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        View.post() 不靠譜的地方你知道多少

        來源:懂視網(wǎng) 責編:小采 時間:2020-11-27 22:31:29
        文檔

        View.post() 不靠譜的地方你知道多少

        View.post() 不靠譜的地方你知道多少:一、前言 有時候,我們會需要用到 View.post() 方法,來將一個 Runnable 發(fā)送到主線程去執(zhí)行。這一切,看似很美好,它最終會通過一個 Handler.post() 方法去執(zhí)行,又避免我們重新定義一個 Handler 對象。 但是,從 Android 7.0(Api leve
        推薦度:
        導讀View.post() 不靠譜的地方你知道多少:一、前言 有時候,我們會需要用到 View.post() 方法,來將一個 Runnable 發(fā)送到主線程去執(zhí)行。這一切,看似很美好,它最終會通過一個 Handler.post() 方法去執(zhí)行,又避免我們重新定義一個 Handler 對象。 但是,從 Android 7.0(Api leve

        一、前言

        有時候,我們會需要用到 View.post() 方法,來將一個 Runnable 發(fā)送到主線程去執(zhí)行。這一切,看似很美好,它最終會通過一個 Handler.post() 方法去執(zhí)行,又避免我們重新定義一個 Handler 對象。

        但是,從 Android 7.0(Api level 24) 開始,View.post() 將不再那么靠譜了,你 post() 出去的 Runnable ,可能永遠也不會有機會執(zhí)行到。

        二、post 在 7.0 的差異

        2.1 post 方法的差異

        前面提到,這個問題只出現(xiàn)在 Android 7.0 上。那么就先從源碼分析 Android 7.0 到底對 View.post() 做了什么改動。

        用 Diff 看一下它們的差異,左邊是 Api Level 24+(以下簡稱 Api24) 的代碼,右邊是 Api level 23-(以下簡稱 Api23) 的代碼。

        很明顯的可以看出來,它們只有在 mAttachInfo 為 null 的時候,執(zhí)行的邏輯才會有差異。

        Api24 中,會調(diào)用 getRunQueue().post(action),而 Api23 會調(diào)用 ViewRootImpl.getRunQueue().post(action) 方法,他們的差異就在這里。

        2.2 Api23 post 的細節(jié)

        先簡單理解一下,ViewRootImpl 是什么。

        ViewRootImpl 可以理解是一個 Activity 的 ViewTree 的根節(jié)點的實例。每個 ViewRootImpl 就是用來管理 DecorView 和 ViewTree。

        ViewRootImpl 中的用來承載 Runnable 的隊列是 sRunQueues ,它一個靜態(tài)的變量,也就是說在 App 的生命周期內(nèi),ViewRootImpl 中的這個消息隊列都是同一個。

        再來看看前面提到的 ViewRootImpl.getRunQueue().post() 到底干了什么?

        post() 方法只是單純的將它包裝成一個 HandlerAction 對象,然后放入 mActions 這個 ArrayList 中。繼續(xù)追查下去就需要知道 mActions 中添加的 HandlerAction 在何時被消費掉了。

        消費 HandlerAction 的地方,是 executeActions() 方法。

        它最終,還是調(diào)用的 handler.postDelayed() ,這沒什么好說的,關(guān)鍵點在于 executeAction() 方法,是在什么時候被調(diào)用的。

        executeAction() 是被 TraversalRunnable 調(diào)用 doTraversa() ,在doTraversa() 方法中,進行調(diào)用的。而 TraversalRunnable 又是通過 Choreographer.postCallBack() 去循環(huán)調(diào)用的。這個 Choreographer 通過 doScheduleCallback() 發(fā)送一個 MSG_DO_SCHEDULE_CALLBACK 類型的消息循環(huán)調(diào)用,間隔就是一個 VSync 的間隔。

        關(guān)于 Choreographer ,不是本文的重點,有興趣可以單獨了解一下。

        所以,在 Api23 以下,executeAction() 是會被循環(huán)調(diào)用,基本上其內(nèi)的 mActions 只要有未執(zhí)行的 Runnable 立刻就會被消費掉。

        所以在 Api23 以下的設(shè)備上,View.post() 基本上是靠譜的,post 出去的 Runnable 都會有機會執(zhí)行到。

        2.3 Api24 的細節(jié)

        再來看看在 Api24 中的實現(xiàn)細節(jié),在 Api24 中,調(diào)用的是 getRunQueue().post() 方法,它操作的是一個 HandlerActionQueue 對象。

        內(nèi)部的結(jié)構(gòu)其實和 Api23 很像,也是維護了一個 HandlerAction 的數(shù)組 mActions 。

        最終消費掉 mActions 的地方,依然是一個 executeActions() 方法。

        回到根本的問題,executeActions() 方法在什么時機會被調(diào)用到,繼續(xù)追查可以看到它在 View.dispatchAttachedToWindow() 方法中,會被調(diào)用。

        既然,executeActions() 方法,在 Api24 及以上,只會在 dispatchAttachedToWindow() 的方法中,才有機會被調(diào)用到,而 View.dispatchAttachedToWindow() 方法,只有在這個 View 通過 addView() 等方法,加入到一個 ViewGroup 的時候,才會被調(diào)用到。這就導致寫在 Layout 布局中的控件,是不會有機會再調(diào)用 addView() 方法的,所以它永遠也得不到執(zhí)行。這也就到時了 Api24 下,View.post() 表現(xiàn)的現(xiàn)象不一致的緣故。

        三、小結(jié)

        View.post() 方法,在不同版本的差異,根本原因還是在于 Api23 和 Api24 中,executeActions() 方法的調(diào)用時機不同,導致 View 在沒有 mAttachInfo 對象的時候,表現(xiàn)不一樣了。

        所以我們在使用的過程中需要慎用,區(qū)分出實際使用的場景,一般規(guī)范自己的代碼即可:

        在 View 已經(jīng)被顯示出來之后,再調(diào)用 View.post() 方法(這個時候 mAttachInfo 已經(jīng)不為空了)。

        盡量避免使用 View.post() 方法,可以直接使用 Handler.post() 方法來替代。

        總結(jié)

        以上所述是小編給大家介紹的View.post() 不靠譜的地方,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

        聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        View.post() 不靠譜的地方你知道多少

        View.post() 不靠譜的地方你知道多少:一、前言 有時候,我們會需要用到 View.post() 方法,來將一個 Runnable 發(fā)送到主線程去執(zhí)行。這一切,看似很美好,它最終會通過一個 Handler.post() 方法去執(zhí)行,又避免我們重新定義一個 Handler 對象。 但是,從 Android 7.0(Api leve
        推薦度:
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 黄色免费网址大全| 亚洲AV无码成人网站在线观看| 一个人晚上在线观看的免费视频| 国内自产拍自a免费毛片| 亚洲最大的黄色网| 丁香花免费完整高清观看| 亚洲国产日韩在线人成下载| 最近中文字幕大全中文字幕免费| 亚洲一区中文字幕久久| 91福利免费视频| 亚洲AV无码国产精品色| 最近2019中文字幕mv免费看| 91在线亚洲综合在线| 国产精品免费视频播放器| 立即播放免费毛片一级| 亚洲欧美国产精品专区久久| 妞干网免费视频在线观看| 免费看黄网站在线看| 亚洲最大AV网站在线观看| 十九岁在线观看免费完整版电影| 亚洲视频在线观看网站| 最近中文字幕免费mv视频7| 美女被爆羞羞网站免费| 久久精品国产亚洲麻豆| 免费黄色福利视频| 亚洲国产无线乱码在线观看| 亚洲午夜无码片在线观看影院猛| 国产无遮挡裸体免费视频在线观看| 久久精品国产亚洲AV香蕉| 免费理论片51人人看电影| 一本到卡二卡三卡免费高 | 久久久免费的精品| 色老板亚洲视频免在线观| 亚洲av麻豆aⅴ无码电影| 久久大香伊焦在人线免费| 亚洲真人日本在线| 8x网站免费入口在线观看| 亚洲AV无码精品国产成人| 亚洲国产精品无码专区| 毛片a级三毛片免费播放| 中文字幕乱理片免费完整的|