當前位置:編程學習大全網 - 源碼下載 - Android ViewRootImpl

Android ViewRootImpl

本文主要分析兩個問題:

1、為什麽View 的繪制流程是從 ViewRootImpl 的performTraversals()方法開始的?

2、View 的invalidate方法是怎麽觸發到ViewRootImpl 的performTraversals()方法的。

在閱讀本文前,最好先了解window的添加過程,Android消息處理機制 和 View 的繪制流程。推薦先閱讀以下文章:

Android Window和WindowManager

Android-消息機制

Android View 的繪制流程

android 源碼註釋的意思是:ViewRootImpl是視圖層次結構的頂部,實現 View 和 WindowManager 之間所需的協議。是 WindowManager Global 的內部實現中重要的組成部分。

View 的繪制流程是從 ViewRootImpl 的performTraversals()方法開始的,那到底是哪裏調用了performTraversals()方法呢,下面我們分析壹下:

1.私有屬性的performTraversals()方法肯定是在內部調用起來的,經過搜索找到是doTraversal()方法調用了。

2.接著找到了,調用了doTraversal() 的TraversalRunnable 類

3.內部只有壹個地方實例化了TraversalRunnable 的實例mTraversalRunnable ,查到到兩個方法內都調用了mTraversalRunnable ,明顯 scheduleTraversals 是主動觸發這個 Runnable 。這就表明調用了scheduleTraversals ()函數的地方都主動觸發了view的刷新。

4.接著我們看壹下 mChoreographer.postCallback 做了什麽

可以看到,最後後走進了scheduleVsyncLocked()方法內。

5.mDisplayEventReceiver 的類 是 FrameDisplayEventReceiver,繼承自

DisplayEventReceiver 。

最後走到這裏就沒了,那麽這個方法是做了什麽呢,這個方法的註釋是這個意思:安排在下壹個顯示幀開始時傳送單個垂直同步脈沖。意思就是,調用了這個方法可以收到系統傳送過來的垂直同步脈沖信號。Android系統每隔16ms就會發送壹個VSYNC信號(VSYNC:vertical synchronization 垂直同步,幀同步),觸發對UI進行渲染。這個垂直同步信對於應用來說了,只有了訂閱了監聽,才能收到。而且是訂閱壹次,收到壹次。

6.既然是在這個類裏面訂閱垂直同步信號的,那回調也應該在這裏。於是找到了以下方法。

native code 調用到 onVsync,這個方法的註釋解釋如下:當接收到垂直同步脈沖時調用。接收者應該渲染壹個幀,然後調用 {@link scheduleVsync} 來安排下壹個垂直同步脈沖。

這個方法的具體實現在前面分析到的FrameDisplayEventReceiver 類裏面。

這裏可以看到,其實mHandler就是當前主線程的handler,當接收到onVsync信號的時候,將自己封裝到Message中,等到Looper處理,最後Looper處理消息的時候就會調用run方法,這裏是Handler的機制,不做解釋。

7.最後,如下圖調用所示,最終從mCallbackQueues取回之前添加的任務再執行run方法,也就是TraservalRunnable的run方法。

總結上面的分析,調用流程如下圖所示如下:

上面我們分析到只要調用了ViewRootImpl 的scheduleTraversals ()方法,最終就能調用了ViewRootImpl 的performTraversals()來開始繪制。那肯定是我們常調用的view刷新的接口,經過壹系列的方法調用,最終調用了ViewRootImpl 的scheduleTraversals ()方法。下面我們分析壹下常用的View 的 invalidate()接口是怎麽調用到了ViewRootImpl 的scheduleTraversals ()方法。

可以看出,invalidate有多個重載方法,但最終都會調用invalidateInternal方法,在這個方法內部,進行了壹系列的判斷,判斷View是否需要重繪,接著為該View設置標記位,然後把需要重繪的區域傳遞給父容器,即調用父容器的invalidateChild方法。

接著我們看ViewGroup#invalidateChild:

由於不斷向上調用父容器的方法,到最後會調用到ViewRootImpl的invalidateChildInParent方法,我們來看看它的源碼,ViewRootImpl#invalidateChildInParent:

最後調用了scheduleTraversals方法,觸發View的工作流程。至此,我們已經完整地分析了壹次調用View 的 invalidate()方法到觸發ViewRootImpl 的scheduleTraversals()方法。

  • 上一篇:在當前的國際貿易形勢下,中國如何發揮自己的比較優勢
  • 下一篇:通達信主力監控精靈的主力買入手數能不能改
  • copyright 2024編程學習大全網