1. 程式人生 > >Activity、Fragment、Service、View生命週期

Activity、Fragment、Service、View生命週期

1. Activity 生命週期

  

  onCreate : 該方法是在Activity被建立時回撥,它是生命週期第一個呼叫的方法,我們在建立Activity時一般都需要重寫該方法,然後在該方法中做一些初始化的操作,如通過setContentView設定介面佈局的資源,初始化所需要的元件資訊等。 
  onStart : 此方法被回撥時表示Activity正在啟動,此時Activity已處於可見狀態,只是還沒有在前臺顯示,因此無法與使用者進行互動。可以簡單理解為Activity已顯示而我們無法看見擺了。 
  onResume

 : 當此方法回撥時,則說明Activity已在前臺可見,可與使用者互動了(處於前面所說的Active/Running形態),onResume方法與onStart的相同點是兩者都表示Activity可見,只不過onStart回撥時Activity還是後臺無法與使用者互動,而onResume則已顯示在前臺,可與使用者互動。當然從流程圖,我們也可以看出當Activity停止後(onPause方法和onStop方法被呼叫),重新回到前臺時也會呼叫onResume方法,因此我們也可以在onResume方法中初始化一些資源,比如重新初始化在onPause或者onStop方法中釋放的資源。 
  onPause
 : 此方法被回撥時則表示Activity正在停止(Paused形態),一般情況下onStop方法會緊接著被回撥。但通過流程圖我們還可以看到一種情況是onPause方法執行後直接執行了onResume方法,這屬於比較極端的現象了,這可能是使用者操作使當前Activity退居後臺後又迅速地再回到到當前的Activity,此時onResume方法就會被回撥。當然,在onPause方法中我們可以做一些資料儲存或者動畫停止或者資源回收的操作,但是不能太耗時,因為這可能會影響到新的Activity的顯示——onPause方法執行完成後,新Activity的onResume方法才會被執行。 
  onStop
 : 一般在onPause方法執行完成直接執行,表示Activity即將停止或者完全被覆蓋(Stopped形態),此時Activity不可見,僅在後臺執行。同樣地,在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的生命週期,官方原始碼註釋中有詳細的描述,作為英語六級勉強飄過的選手,我頂著巨大的壓力翻譯了一下。

  1. Creation(建立)
  • Constructors(建構函式):有一種形式的建構函式會在View在程式碼中被建立時呼叫,另一種形式的建構函式會在View從layout加載出來時被呼叫。
    第二種形式的建構函式會解析和應用layout檔案中定義的任何屬性。
  • onFinishInflate():該方法當View及其子View從XML檔案中載入完成後會被呼叫。
  1. Layout(佈局)
  • onMeasure(int, int):該方法在計算當前View及其所有子View尺寸大小需求時會被呼叫。
  • onLayout(boolean, int, int, int, int):該方法在當前View需要為其子View分配尺寸和位置時會被呼叫。
  • onSizeChanged(int, int, int, int):該方法在當前View尺寸變化時被呼叫。
  1. Drawing(繪製)
  • onDraw(android.graphics.Canvas):該方法在當前View需要呈現其內容時被呼叫。
  1. Event processing(事件處理)
  • onKeyDown(int, KeyEvent):該方法在一個物理按鍵事件發生時被呼叫。
  • onKeyUp(int, KeyEvent):該方法在一個物理按鍵彈起事件發生時被呼叫。
  • onTrackballEvent(MotionEvent):該方法在一個軌跡球運動事件發生時被呼叫。
  • onTouchEvent(MotionEvent):該方法在一個觸控式螢幕幕運動事件發生時被呼叫。
  1. Focus(聚焦)
  • onFocusChanged(boolean, int, android.graphics.Rect):該方法在當前View獲得或失去焦點時被呼叫。
  • onWindowFocusChanged(boolean):該方法在包含當前View的window獲得或失去焦點時被呼叫。
  1. 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()
  1. 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()
  1. 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()