Android View的生命周期



http://www.jianshu.com/p/08e6dab7886e

http://www.jianshu.com/p/08e6dab7886e

http://www.jianshu.com/p/08e6dab7886e



Android View的生命周期

字數2056 閱讀656 評論0 

View生命周期相關方法

View是什么?官方源碼注釋中的定義:這個類是用戶接口的基礎構件。View表示屏幕上的一塊矩形區域,負責繪制這個區域和事件處理。
View是所有widget類的基類,Widget類用於創建交互式UI構件(按鈕,輸入框等)。
View類的ViewGroup子類是layout的基類,Layout是一個不可見的容器,它保存着View(或ViewGroup)並定義這些View的layout 屬性。

簡單點說,View就是屏幕上的一塊矩形區域,我們可以在這塊區域繪制我們想讓用戶看到的圖形。

關於View的生命周期,官方源碼注釋中有詳細的描述,作為英語六級勉強飄過的選手,我頂着巨大的壓力翻譯了一下。

  1. Creation(創建)
    • Constructors(構造函數):有一種形式的構造函數會在View在代碼中被創建時調用,另一種形式的構造函數會在View從layout加載出來時被調用。
      第二種形式的構造函數會解析和應用layout文件中定義的任何屬性。
    • onFinishInflate():該方法當View及其子View從XML文件中加載完成后會被調用。
  2. Layout(布局)
    • onMeasure(int, int):該方法在計算當前View及其所有子View尺寸大小需求時會被調用。
    • onLayout(boolean, int, int, int, int):該方法在當前View需要為其子View分配尺寸和位置時會被調用。
    • onSizeChanged(int, int, int, int):該方法在當前View尺寸變化時被調用。
  3. Drawing(繪制)
    • onDraw(android.graphics.Canvas):該方法在當前View需要呈現其內容時被調用。
  4. Event processing(事件處理)
    • onKeyDown(int, KeyEvent):該方法在一個物理按鍵事件發生時被調用。
    • onKeyUp(int, KeyEvent):該方法在一個物理按鍵彈起事件發生時被調用。
    • onTrackballEvent(MotionEvent):該方法在一個軌跡球運動事件發生時被調用。
    • onTouchEvent(MotionEvent):該方法在一個觸摸屏幕運動事件發生時被調用。
  5. Focus(聚焦)
    • onFocusChanged(boolean, int, android.graphics.Rect):該方法在當前View獲得或失去焦點時被調用。
    • onWindowFocusChanged(boolean):該方法在包含當前View的window獲得或失去焦點時被調用。
  6. Attaching(附上)
    • onAttachedToWindow():該方法在當前View被附到一個window上時被調用。
    • onDetachedFromWindow():該方法在當前View從一個window上分離時被調用。
    • onVisibilityChanged(View, int):該方法在當前View或其祖先的可見性改變時被調用。
    • onWindowVisibilityChanged(int):該方法在包含當前View的window可見性改變時被調用。

上述方法是View生命周期中涉及到的比較重要的一部分,View類中包含了很多的方法和屬性,有興趣的話各位可以自己研究一下。

View生命周期相關方法調用順序

簡單的了解了View生命周期相關的幾個方法,接着我們看看這些方法調用的順序是怎樣的,我們針對View的可見性分三種情況來觀察。

  1. android:visibility=visible
    • 創建
      I/TestView: TestView(Context context, AttributeSet attrs)
      I/TestView: onFinishInflate()
      I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{2192bad9 I.E..... R.....ID 0,0-0,0} visibility = 4
      I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{2192bad9 V.E..... R.....ID 0,0-0,0} visibility = 0
      I/TestView: onAttachedToWindow()
      I/TestView: onWindowVisibilityChanged(int visibility) visibility = 0
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016
      I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 2192 oldw = 0 oldh0
      I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2248
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
      I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 1996 oldw = 1328 oldh2192
      I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2052
      I/TestView: onDraw(Canvas canvas)
      I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = true
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
      I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = false left = 56 top = 56 right = 1384 bottom = 2052
      I/TestView: onDraw(Canvas canvas)
    • 銷毀
      I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = false
      I/TestView: onWindowVisibilityChanged(int visibility) visibility = 8
      I/TestView: onDetachedFromWindow()
  2. android:visibility=invisible
    • 創建
      I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.example.junyizhou.rxjavademo.TestView{3ead3d52 I.ED.... ........ 0,0-0,0} visibility = 4
      I/TestView: TestView(Context context, AttributeSet attrs)
      I/TestView: onFinishInflate()
      I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 I.E..... R.....ID 0,0-0,0} visibility = 4
      I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 V.E..... R.....ID 0,0-0,0} visibility = 0
      I/TestView: onAttachedToWindow()
      I/TestView: onWindowVisibilityChanged(int visibility) visibility = 0
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016
      I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 2192 oldw = 0 oldh0
      I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2248
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
      I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 1996 oldw = 1328 oldh2192
      I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2052
      I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = true
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
      I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
      I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = false left = 56 top = 56 right = 1384 bottom = 2052
    • 銷毀
      I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = false
      I/TestView: onWindowVisibilityChanged(int visibility) visibility = 8
      I/TestView: onDetachedFromWindow()
  3. android:visibility=gone
    • 創建
      I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.example.junyizhou.rxjavademo.TestView{3ead3d52 G.ED.... ......I. 0,0-0,0} visibility = 8
      I/TestView: TestView(Context context, AttributeSet attrs)
      I/TestView: onFinishInflate()
      I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 I.E..... R.....ID 0,0-0,0} visibility = 4
      I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 V.E..... R.....ID 0,0-0,0} visibility = 0
      I/TestView: onAttachedToWindow()
      I/TestView: onWindowVisibilityChanged(int visibility) visibility = 0
      I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = true
    • 銷毀
      I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = false
      I/TestView: onWindowVisibilityChanged(int visibility) visibility = 8
      I/TestView: onDetachedFromWindow()

總結

從中我們可以看出:

  1. View默認為可見的,不是默認值時先調用onVisibilityChanged(),但是此時該View的尺寸、位置等信息都不知道。
  2. 可見性改變后才是調用帶有兩個參數的構造函數,當然,如果該View不是在layout中定義的話,會調用一個參數的構造函數。
  3. 從XMl文件中inflate完成(onFinishInflate())。
  4. 將View加到window中(View是gone的,那么View創建生命周期也就結束)。
  5. 測量view的長寬(onMeasure())。
  6. 定位View 在父View中的位置(onLayout()),若View是invisible,則View的創建生命周期結束。
  7. 繪制View的content(onDraw()),只有可見的View才在window中繪制。
  8. View的銷毀流程和可見性沒有關系。

綜上所述:View的關鍵生命周期為:

[改變可見性] --> 構造View() --> onFinishInflate() --> onAttachedToWindow() --> onMeasure() --> onSizeChanged() --> onLayout() --> onDraw() --> onDetackedFromWindow()

自定義View時我們不可避免的要和View生命周期相關函數打交道,可能需要重新其中的某個或某幾個來滿足定制的需求,因此了解View的生命周期是Android程序猿進階的必經之路。當然,我們沒必要重新所有的方法,如果我們只是單純的想把一個Bitmap畫到View上,那我們只要重寫View的onDraw方法就可以了,事實上自定義View的大部分情況我們也只是關注這個方法。






onDetachedFromWindow

已有 3974 次閱讀  2012-04-18 17:42

在學習android的Handler 時用到自定義的View ,繼承后重寫View 的onDetachedFromWinfow()方法。

該方法的作用是當view離開窗口時調用(

This is called when the view is detached from a window. At this point it no longer has a surface for drawing.

)。

在做具體測試時發現,當點擊返回鍵時,可以正常調用該方法;當點擊Home鍵退出時無法正常調用onDetachedFromWindow()。





http://blog.csdn.net/ymlxku/article/details/39079643?utm_source=tuicool&utm_medium=referral


http://blog.csdn.net/ymlxku/article/details/39079643?utm_source=tuicool&utm_medium=referral

 

android——View/ViewGroup的"生命周期"

標簽: AndroidUI 2738人閱讀 評論(0) 收藏 舉報  分類:

如題View與ViewGroup里的方法調用過程總結如下:

1.首先,Activity onCreate並初始化view

2.然后,Activity onResume后調用view的onAttachedToWindow,因此常常在onAttachedToWindow方法中做初始化工作,比如注冊一些廣播、開始動畫等等……

3.接下來,如果設置了背景則調用onDraw,之后倘若是viewgroup則調用dispatchDraw。

說明:dispatchDraw()主要是分發給子組件進行繪制,我們通常定制組件的時候重寫的是onDraw()方法。值得注意的是ViewGroup容器組件的繪制,當它沒有背景時直接調用的是dispatchDraw()方法, 而繞過了draw()方法,當它有背景的時候就調用draw()方法,而draw()方法里包含了dispatchDraw()方法的調用。因此要在ViewGroup上繪制東西的時候往往重寫的是dispatchDraw()方法而不是onDraw()方法,或者自定制一個Drawable,重寫它的draw(Canvas c)和 getIntrinsicWidth(),getIntrinsicHeight()方法,然后設為背景。

4.最后,當點擊回退鍵時,Activity onDestroy后才調用onDetachedFromWindow,這時我們就在這個方法做一些收尾工作,如:取消廣播注冊、停止動畫等等。

說明:onDraw與dispatchDraw將可能由於setVisible或onresume調用多次,而onAttachedToWindow與onDetachedFromWindow在創建與銷毀view的過程中只會調用一次。

5.此外在創建期間還會多次調用onMeasure和onLayout。


以下是日志詳情說明,有興趣的孩子自己寫demo

 

點擊返回鍵

 

viewgroup屬性中設置背景

 

viewgroup無背景時,viewgroup僅調用了dispatchDraw,不調用onDraw。


onMeasure和onLayout


 







注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com