歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android中View繪制流程以及invalidate()等相關方法分析

Android中View繪制流程以及invalidate()等相關方法分析

日期:2017/3/1 10:40:34   编辑:Linux編程
整個View樹的繪圖流程是在ViewRoot.java類的performTraversals()函數展開的,該函數做的執行過程可簡單概況為根據之前

設置的狀態,判斷是否需要重新計算視圖大小(measure)、是否重新需要安置視圖的位置(layout)、以及是否需要重繪(draw),其框架過程如下:

接下來溫習一下整個View樹的結構,對每個具體View對象的操作,其實就是個遞歸的實現。

本文相關代碼下載

免費下載地址在 http://linux.linuxidc.com/

用戶名與密碼都是www.linuxidc.com

具體下載目錄在 /2012年資料/1月/9日/Android中View繪制流程以及invalidate()等相關方法分析/

流程一: mesarue()過程

主要作用:為整個View樹計算實際的大小,即設置實際的高(對應屬性:mMeasuredHeight)和寬(對應屬性:mMeasureWidth),

每個View的控件的實際寬高都是由父視圖和本身視圖決定的。

具體的調用鏈如下:

ViewRoot根對象地屬性mView(其類型一般為ViewGroup類型)調用measure()方法去計算View樹的大小,回調View/ViewGroup

對象的onMeasure()方法,該方法實現的功能如下:

1、設置本View視圖的最終大小,該功能的實現通過調用setMeasuredDimension()方法去設置實際的高(對應屬性:

mMeasuredHeight)和寬(對應屬性:mMeasureWidth) ;

2 、如果該View對象是個ViewGroup類型,需要重寫該onMeasure()方法,對其子視圖進行遍歷的measure()過程。

2.1 對每個子視圖的measure()過程,是通過調用父類ViewGroup.java類裡的measureChildWithMargins()方法去實現,

該方法內部只是簡單地調用了View對象的measure()方法。(由於measureChildWithMargins()方法只是一個過渡層,更簡單

的做法是直接調用View對象的measure()方法)

整個measure調用流程就是個樹形的遞歸過程

measure函數原型為 View.java 該函數不能被重載

  1. public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
  2. //....
  3. //回調onMeasure()方法
  4. onMeasure(widthMeasureSpec, heightMeasureSpec);
  5. //more
  6. }

為了大家更好的理解,采用“二B程序員”的方式利用偽代碼描述該measure流程

  1. // measure()過程 ViewRoot.java
  2. // 發起measure()的"發號者"在ViewRoot.java裡的performTraversals()方法, mView.measure()
  3. private void performTraversals(){
  4. //...
  5. View mView ;
  6. mView.measure(h,l) ;
  7. //....
  8. }
  9. //回調View視圖裡的onMeasure過程
  10. private void onMeasure(int height , int width){
  11. //設置該view的實際寬(mMeasuredWidth)高(mMeasuredHeight)
  12. //1、該方法必須在onMeasure調用,否者報異常。
  13. setMeasuredDimension(h , l) ;
  14. //2、如果該View是ViewGroup類型,則對它的每個子View進行measure()過程
  15. int childCount = getChildCount() ;
  16. for(int i=0 ;i<childCount ;i++){
  17. //2.1、獲得每個子View對象引用
  18. View child = getChildAt(i) ;
  19. //整個measure()過程就是個遞歸過程
  20. //該方法只是一個過濾器,最後會調用measure()過程 ;或者 measureChild(child , h, i)方法都
  21. measureChildWithMargins(child , h, i) ;
  22. //其實,對於我們自己寫的應用來說,最好的辦法是去掉框架裡的該方法,直接調用view.measure(),如下:
  23. //child.measure(h, l)
  24. }
  25. }
  26. //該方法具體實現在ViewGroup.java裡 。
  27. protected void measureChildWithMargins(View v, int height , int width){
  28. v.measure(h,l)
  29. }
Copyright © Linux教程網 All Rights Reserved