iT邦幫忙

2022 iThome 鐵人賽

DAY 29
0
Mobile Development

新手向Android&Kotlin學習紀錄30天系列 第 29

第29天 單一個 Activity 生命週期介紹

  • 分享至 

  • xImage
  •  

雖然不像是人類生老病死的階段,但Acitvity在應用程式中的生命週期,也分成好幾階段,從建立到銷毀、可見不可見、焦點,都影響著開發人員的心情(?),更別說多個Activities跟fragments的時候...。生命週期絕對是需要好好了解的重要一環,否則容易一不小心就踩坑還不自覺。

生命週期喜蝦米

Acitvity生命週期是其在其生命週期內可呈現的狀態組合。生命週期是指Acitvity從最初建立到刪除且系統回收其記憶體的這段時間。
當使用者在應用程式 (包括應用程式內外) 的Acitvities間進行瀏覽時,這些Acitvity會在生命週期中的不同狀態之間進行轉換。
下圖是官網抓的圖,清楚地畫出的這些狀態間彼此的關係:
這張圖就是全部內容(無誤),那今天就介紹到這裡

如何得知現在在週期哪一階段

我們可以使用logcat日誌紀錄來得知現在處於哪一階段

  1. 首先把上面那張圖的生命週期都回呼出來覆寫,在MainActivity的{}中,但不要在onCreat()裡面,輸入要覆寫的函數名,如:onStart、onReSume,就可以看到IDE給出選項了,或是Ctrl+O叫出覆寫成員(Override Members)的視窗點選需要覆寫的成員。
  2. 然後都在他們的函數本體{}內鍵入logd,按下enter鍵就會出現:
    第1個參數TAG是標籤,第2個參數是message,兩者都可以自訂。現在先不用更改也沒關係。
    //以onStart()為例
     override fun onStart() {
        super.onStart()
        Log.d(TAG, "onStart: ")
    }
    
    一般會將TAG命名成所在的類別名:
    private val TAG = "MainActivity"
    
  3. 開啟下方logcat日誌視窗,運行應用程式觀察記錄訊息的「優先順序」,也就是訊息的重要性由高至低排列:
    • Assert 開發者預計絕不會發生的問題。
    • Error 已經引發錯誤的問題,對應Log.e()。
    • Warn 尚不是錯誤的潛在問題,對應Log.w()。
    • Info 常規使用情況的預期日誌消息,對應Log.i()。
    • Debug 在開發期間有用的調試日誌消息,對應Log.d()。
    • Verbose 所有日誌消息,對應Log.v()。
    • 長度超過23個字符的標記名稱在logcat 輸出中會被截斷。


因為這裡面的訊息非常多我們不需要的資訊,所以依照log.d(...)選擇對的訊息等級Debug(紅框處),並在搜尋欄中以「標籤」篩選出需要的紀錄(綠框處)。

  • logcat 視窗顯示的詳細程度從少到多的順序是: Error、Warn、Info、Debug、Verbose。意思是從消息級別選單(紅框處)選擇Error只會顯示Error級別日誌訊息;選擇Warn的話,會列出Error和Warn級別的訊息...以此類推,選擇Verbose會顯示重要和不重要的所有日誌訊息。

適當下log,logcat可以在開發過程中,可提供我們很多資訊來釐清邏輯、跟產生的效果是否如預期、判斷出錯的來源、當然還有生命週期...等狀態,讓我們對應用程式運行的狀態有更好的掌握,除錯也能更有效率。

android文檔-log
android文檔-logcat

各生命週期簡介:

1.開啟Activity

生命週期順序 : Launch ->onCreate -> onStart -> onResume
如果都在各生命週期設置好log了,點下運行鍵會看到下圖的訊息依序在logcat視窗中跳出來:
每條訊息都包含日期時間+專案的名稱+log的標籤和訊息

  • onCreate() Activity第一次被建立的時候呼叫(之後會調用onRestart() )。在onCreate()方法中完成初始化操作:載入佈局、繫結事件...等。
  • onStart() Activity由不可見變為可見的時候呼叫。(非棧頂到棧頂)。
  • onResume() 在Activity準備好和使用者互動的時候呼叫。(棧頂)。

2.中斷後再返回Activity

生命週期順序 : ...->onResume -> 開啟另一個App(此app退到背景) -> onPause -> onStop -> 再次返回此Activity -> onRestart -> onStart -> onResume

比如說你點選其他app(如下圖)或有其他事件(如來電),這時Activity就會退到後台,變成用戶看不見的狀態,這時還不會銷毀(onDestroy)。

  • onPause() : 準備去啟動或恢復另一個活動時呼叫。應用程式就不再有焦點,用戶無法與之互動。直到onResume()或onStop()之前,Activity 會保持此狀態。通常可以在這時期,將一些消耗CPU的資源釋放,以及保存關鍵資訊,但執行速度要快,否則會影響棧頂正要使用的其他Activity。
  • onStop() : 應用程式完全不可見時呼叫,儘管Activity已經停止,但 Activity 物件仍位於背景的記憶體中,系統並未刪除該Activity,暫時保留住資源等用戶隨時回來。
    • 註: 但新的Activity是對話框式的話,就不會進到onStop(),例如 : 運行中( onResume )->點選"分享icon"(出現分享視窗,但activity部分可見)-> onPause -> 取消分享,返回Activity -> onResume

  • onRestart() : 從onStop變為onResume前調用,表示重新開始。(這個Activity是昨天的範例就續用了XD)

3.關閉應用程式

生命週期順序: ...->onResume->返回鍵 -> onPause -> onStop -> onDestroy
比如從後台滑掉應用程式或按下裝置上的返回鍵。只剩onDestroy沒介紹:

  • onDestroy() 在Activity被銷毀前調用,完成釋放記憶體操作,之後Activity就變銷毀狀態。

3種生存期

以上7個生命週期,除了onRestart(),其他都是兩兩相對的,據此可分為3種生存期(節錄自Android第一行代碼及網路文章整理):

  1. 完整生存期: Activity在 onCreate()到onDestroy() 間所經歷的就是完整生存期,Activity完成各種從初始化到被銷毀釋放內存的操作。Activity需在onCreate()完成全域性狀態的設定,如定義佈局檔。並在onDestroy()釋放掉所有占用的資源。

  2. 可見生存期: 是指Activity在 onStart()到onStop() 間所經歷的時期。對用戶來說在可見生存期總是可見但不一定可以互動。透過這覆寫這兩個函數,合理管理用戶可見的資源。例如,你可以在 onStart() 方法裡註冊一個 broadcastreceiver 用於監控影響使用者介面的動態,並且當使用者不再看到你的顯示內容時,在 onStop() 方法裡登出掉它。系統會在 Activity 的整個生存期內多次呼叫 onStart() 和onStop(),因為 Activity 可能會在顯示和隱藏之間不斷地來回切換。

  3. 前台生存期: 是指Activity在 onResume()到onPause() 間所經歷的時期。在這時期,Activity總是處於運行階段,可與用戶互動,是我們最常看見、接觸的時期。Activity可以頻繁地進入和退出前台,例如 : 當裝置進入休眠時或者彈出一個對話方塊時,onPause() 就會被呼叫。因為這個狀態可能會經常發生轉換,為了避免切換遲緩引起的使用者等待,這兩個方法中的應該相當地輕量化

小結

這篇只是冰山一角的一個Activity的生命週期簡介,但通常App都不會只一個Activity,也許多個,也許還加上Fragments(也有不同的生命週期),那各自生命週期、可見不可見、焦點在哪,每個頁面都需要一一注意處理,所以一定得花時間了解,這樣坑應該會少踩很多,雖然通常都是踩下去才知道是坑啦QQ,但多了解一點希望坑踩淺淺就可以抽身,共勉之。

參考
Android第一行代碼
了解Activity 生命週期
codelab-活動生命週期的各個階段
Android 生命週期備忘單 — 第一部分:單一活動


上一篇
第28天 認識Activity、Toast、Snackbar
下一篇
第30天 使用者介面本地化 - 多國語系 & 變更Launch Icon
系列文
新手向Android&Kotlin學習紀錄30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言