Activity、Fragment、Service、View生命週期
1. Activity 生命週期
onCreate : 該方法是在Activity被建立時回撥,它是生命週期第一個呼叫的方法,我們在建立Activity時一般都需要重寫該方法,然後在該方法中做一些初始化的操作,如通過setContentView設定介面佈局的資源,初始化所需要的元件資訊等。
onStart : 此方法被回撥時表示Activity正在啟動,此時Activity已處於可見狀態,只是還沒有在前臺顯示,因此無法與使用者進行互動。可以簡單理解為Activity已顯示而我們無法看見擺了。
onResume
onPause
onStop
onRestart :表示Activity正在重新啟動,當Activity由不可見變為可見狀態時,該方法被回撥。這種情況一般是使用者打開了一個新的Activity時,當前的Activity就會被暫停(onPause和onStop被執行了),接著又回到當前Activity頁面時,onRestart方法就會被回撥。
onDestroy :此時Activity正在被銷燬,也是生命週期最後一個執行的方法,一般我們可以在此方法中做一些回收工作和最終的資源釋放。
2. Fragment 生命週期
Fragment每個生命週期方法的意義、作用(注意紅色的不是生命週期方法):
setUserVisibleHint():設定Fragment可見或者不可見時會呼叫此方法。在該方法裡面可以通過呼叫getUserVisibleHint()獲得Fragment的狀態是可見還是不可見的,如果可見則進行懶載入操作。
onAttach():執行該方法時,Fragment與Activity已經完成繫結,該方法有一個Activity型別的引數,代表繫結的Activity,這時候你可以執行諸如mActivity = activity的操作。
onCreate():初始化Fragment。可通過引數savedInstanceState獲取之前儲存的值。
onCreateView():初始化Fragment的佈局。載入佈局和findViewById的操作通常在此函式內完成,但是不建議執行耗時的操作,比如讀取資料庫資料列表。
onActivityCreated():執行該方法時,與Fragment繫結的Activity的onCreate方法已經執行完成並返回,在該方法內可以進行與Activity互動的UI操作,所以在該方法之前Activity的onCreate方法並未執行完成,如果提前進行互動操作,會引發空指標異常。
onStart():執行該方法時,Fragment由不可見變為可見狀態。
onResume():執行該方法時,Fragment處於活動狀態,使用者可與之互動。
onPause():執行該方法時,Fragment處於暫停狀態,但依然可見,使用者不能與之互動。
onSaveInstanceState():儲存當前Fragment的狀態。該方法會自動儲存Fragment的狀態,比如EditText鍵入的文字,即使Fragment被回收又重新建立,一樣能恢復EditText之前鍵入的文字。
onStop():執行該方法時,Fragment完全不可見。
onDestroyView():銷燬與Fragment有關的檢視,但未與Activity解除繫結,依然可以通過onCreateView方法重新建立檢視。通常在ViewPager+Fragment的方式下會呼叫此方法。
onDestroy():銷燬Fragment。通常按Back鍵退出或者Fragment被回收時呼叫此方法。
onDetach():解除與Activity的繫結。在onDestroy方法之後呼叫。
Fragment生命週期執行流程(注意紅色的不是生命週期方法):
Fragment建立:setUserVisibleHint()->onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume();
Fragment變為不可見狀態(鎖屏、回到桌面、被Activity完全覆蓋):onPause()->onSaveInstanceState()->onStop();
Fragment變為部分可見狀態(開啟Dialog樣式的Activity):onPause()->onSaveInstanceState();
Fragment由不可見變為活動狀態:onStart()->OnResume();
Fragment由部分可見變為活動狀態:onResume();
退出應用:onPause()->onStop()->onDestroyView()->onDestroy()->onDetach()(注意退出不會呼叫onSaveInstanceState方法,因為是人為退出,沒有必要再儲存資料);
Fragment被回收又重新建立:被回收執行onPause()->onSaveInstanceState()->onStop()->onDestroyView()->onDestroy()->onDetach(),重新建立執行onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume()->setUserVisibleHint();
橫豎屏切換:與Fragment被回收又重新建立一樣。
3. Service 生命週期
在Service
的生命週期裡,常用的有:
- 4個手動呼叫的方法
手動呼叫方法 | 作用 |
---|---|
startService() | 啟動服務 |
stopService() | 關閉服務 |
bindService() | 繫結服務 |
unbindService() | 解綁服務 |
- 5個自動呼叫的方法
內部自動呼叫的方法 | 作用 |
---|---|
onCreat() | 建立服務 |
onStartCommand() | 開始服務 |
onDestroy() | 銷燬服務 |
onBind() | 繫結服務 |
onUnbind() | 解綁服務 |
4. View 生命週期
View的關鍵生命週期為:
[改變可見性] --> 構造View() --> onFinishInflate() --> onAttachedToWindow()
--> onMeasure() --> onSizeChanged() --> onLayout() --> onDraw()
--> onDetackedFromWindow()
View是什麼?官方原始碼註釋中的定義:這個類是使用者介面的基礎構件。View表示螢幕上的一塊矩形區域,負責繪製這個區域和事件處理。
View是所有widget類的基類,Widget類用於建立互動式UI構件(按鈕,輸入框等)。
View類的ViewGroup子類是layout的基類,Layout是一個不可見的容器,它儲存著View(或ViewGroup)並定義這些View的layout 屬性。
簡單點說,View就是螢幕上的一塊矩形區域,我們可以在這塊區域繪製我們想讓使用者看到的圖形。
關於View的生命週期,官方原始碼註釋中有詳細的描述,作為英語六級勉強飄過的選手,我頂著巨大的壓力翻譯了一下。
- Creation(建立)
- Constructors(建構函式):有一種形式的建構函式會在View在程式碼中被建立時呼叫,另一種形式的建構函式會在View從layout加載出來時被呼叫。
第二種形式的建構函式會解析和應用layout檔案中定義的任何屬性。 - onFinishInflate():該方法當View及其子View從XML檔案中載入完成後會被呼叫。
- Layout(佈局)
- onMeasure(int, int):該方法在計算當前View及其所有子View尺寸大小需求時會被呼叫。
- onLayout(boolean, int, int, int, int):該方法在當前View需要為其子View分配尺寸和位置時會被呼叫。
- onSizeChanged(int, int, int, int):該方法在當前View尺寸變化時被呼叫。
- Drawing(繪製)
- onDraw(android.graphics.Canvas):該方法在當前View需要呈現其內容時被呼叫。
- Event processing(事件處理)
- onKeyDown(int, KeyEvent):該方法在一個物理按鍵事件發生時被呼叫。
- onKeyUp(int, KeyEvent):該方法在一個物理按鍵彈起事件發生時被呼叫。
- onTrackballEvent(MotionEvent):該方法在一個軌跡球運動事件發生時被呼叫。
- onTouchEvent(MotionEvent):該方法在一個觸控式螢幕幕運動事件發生時被呼叫。
- Focus(聚焦)
- onFocusChanged(boolean, int, android.graphics.Rect):該方法在當前View獲得或失去焦點時被呼叫。
- onWindowFocusChanged(boolean):該方法在包含當前View的window獲得或失去焦點時被呼叫。
- Attaching(附上)
- onAttachedToWindow():該方法在當前View被附到一個window上時被呼叫。
- onDetachedFromWindow():該方法在當前View從一個window上分離時被呼叫。
- onVisibilityChanged(View, int):該方法在當前View或其祖先的可見性改變時被呼叫。
- onWindowVisibilityChanged(int):該方法在包含當前View的window可見性改變時被呼叫。
上述方法是View生命週期中涉及到的比較重要的一部分,View類中包含了很多的方法和屬性,有興趣的話各位可以自己研究一下。
View生命週期相關方法呼叫順序
簡單的瞭解了View生命週期相關的幾個方法,接著我們看看這些方法呼叫的順序是怎樣的,我們針對View的可見性分三種情況來觀察。
- 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()
- 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()
- 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()