1. 事前準備
在本程式碼研究室中,您將瞭解 Android 的基本要素:活動生命週期。
在其生命週期中,活動會透過不同狀態轉換,有時還會返回各狀態。此狀態轉換稱為活動生命週期。
在 Android 中,活動是與使用者互動的進入點。
過去,一項活動會在應用程式中顯示一個螢幕。根據目前的最佳做法,其中一項活動可能會依需求切換不同螢幕,以顯示多個畫面。
當系統回收該活動的資源時,活動生命週期會從建立活動延伸至刪除。當使用者進入及退出活動時,每個活動會在活動生命週期中的不同狀態之間進行轉換。
身為 Android 開發人員,您必須瞭解活動生命週期。如果您的活動未正確回應生命週期狀態變更,應用程式可能會產生異常錯誤、造成使用者混淆行為,或耗用過多 Android 系統資源。瞭解 Android 生命週期,並正確回應生命週期狀態變更是 Android 開發作業中相當重要的一環。
必要條件
- 瞭解什麼是活動,以及在應用程式中建立活動的方式
- 瞭解活動的
onCreate()
方法用途,以及該方法執行的運算種類
課程內容
- 如何將記錄資訊列印至 Logcat
Activity
生命週期的基本概念,以及活動於狀態之間變動時叫用的回呼。- 如何覆寫生命週期回呼方法,以在活動生命週期的不同時間點執行運算。
建構項目
- 修改名稱為 Dessert Clicker 的範例應用程式,以新增 Logcat 中顯示的記錄資訊。
- 覆寫生命週期回呼方法,並記錄活動狀態的變更。
- 執行應用程式,並記下活動開始、停止和繼續時的記錄資訊。
- 實作
rememberSaveable
,保留因裝置設定變更而可能遺失的應用程式資料。
2. 應用程式總覽
在本程式碼研究室中,您將使用名為 Dessert Clicker 的範例應用程式。在 Dessert Clicker 中,每當使用者輕觸螢幕上的甜點,應用程式就會為使用者「購買」甜點。應用程式會在版面配置中更新下列項目的值:
- 購買的甜點數量
- 「已購買」甜點的總收益
此應用程式含有數個與 Android 生命週期相關的錯誤。例如,在某些情況下,應用程式會將甜點值重設為 0。瞭解 Android 生命週期有助於瞭解問題發生的原因與修正方法。
下載範例程式碼
在 Android Studio 中開啟 basic-android-kotlin-compose-training-dessert-clicker
資料夾。
3. 探索生命週期方法並新增基本記錄
每個活動都具有生命週期。該字詞類比的是植物和動物的生命週期,如同蝴蝶的生命週期。蝴蝶的不同狀態,顯示其從卵、毛蟲、蛹、蝴蝶到死亡等階段的成長。
同樣地,活動生命週期包括活動可能經歷的不同狀態,從活動首次初始化到其刪除,期間作業系統 (OS) 會回收其記憶體。一般來說,程式的進入點為 main()
方法。不過,Android 活動會先使用 onCreate()
方法。此方法等同於上述範例中的卵子階段。在本課程中,您已多次使用活動,您可能會認得 onCreate()
方法。當使用者啟動您的應用程式、在活動間瀏覽、在應用程式內部或外部瀏覽時,活動皆會改變狀態。
下圖顯示所有活動生命週期狀態。顧名思義,這些狀態代表活動的狀態。請注意,與蝴蝶生命週期不同的是,活動在整個生命週期中來回切換,而不是只朝單一方向移動。
通常,當活動生命週期狀態變更時,您會想變更部分行為或執行某些程式碼。因此,Activity
類別本身和 Activity
的任何子類別 (例如 ComponentActivity
) 會實作一系列生命週期回呼方法。當活動狀態改變時,Android 將會叫用這些回呼,而您可以在自身活動中覆寫此類方法,以執行回應生命週期狀態變更的工作。下圖顯示生命週期狀態,以及可用的可覆寫回呼。
請務必瞭解 Android 何時叫用可覆寫的回呼,以及每個回呼方法的處理方式,但這兩個圖表都很複雜,可能會混淆。在本程式碼研究室中,您將需要進行一些偵測工作並對 Android 活動生命週期建立一定的瞭解,而不只是瞭解每個狀態和回呼的意義。
步驟 1:檢查 onCreate()
方法並新增記錄
如要瞭解 Android 生命週期發生的情況,瞭解呼叫各種生命週期方法的時機相當實用。這份資訊可協助您在 Dessert Clicker 應用程式中找出問題所在。
要判斷這項資訊,最簡單的方法是使用 Android 記錄功能。記錄功能可讓您在應用程式執行期間,將簡短訊息寫入主控台,用於查看不同回呼的觸發時機。
- 執行 Dessert Clicker 應用程式,然後在甜點相片上輕觸數次。請注意,已售出甜點值和總金額的變化情況。
- 開啟
MainActivity.kt
並檢查此活動的onCreate()
方法:
override fun onCreate(savedInstanceState: Bundle?) {
// ...
}
在活動生命週期圖表中,您可能認出 onCreate()
方法,因為您先前使用過此回呼。這是每項活動都必須實作的方法。onCreate()
是您為活動執行任何一次性初始化作業的方法。舉例來說,在 onCreate()
中呼叫 setContent()
,即可指定活動的 UI 版面配置。
當活動初始化後,OS 會在記憶體中建立新的 Activity
物件時,系統會呼叫一次 onCreate()
生命週期方法。執行 onCreate()
後,系統會將活動視為已建立。
- 在
MainActivity.kt
頂層的類別宣告class MainActivity
的上方新增下列常數。
建議您在檔案中宣告 TAG
常數,因為該值的值不會改變。
如要將其標示為編譯時間常數,請在宣告變數時使用 const
。編譯時間常數是編譯期間已知的值。
private const val TAG = "MainActivity"
- 在
onCreate()
方法中,於呼叫super.onCreate()
後新增下列程式碼:
Log.d(TAG, "onCreate Called")
- 視需要匯入
Log
類別 (Mac 上請按Alt+Enter
或Option+Enter
,然後選取匯入)。如果您已啟用自動匯入功能,系統會自動執行這項操作。
import android.util.Log
Log
類別會將訊息寫入「Logcat」。「Logcat」是記錄訊息的主控台。此處會顯示來自 Android 的應用程式相關訊息,包括您透過 Log.d()
方法或其他 Log
類別方法明確傳送至記錄的訊息。
Log
指示有三個重要方面:
- 記錄訊息的優先順序,也就是訊息的重要性。在這種情況下,
Log.v()
會記錄詳細訊息。Log.d()
方法會寫入偵錯訊息。Log
類別中的其他方法包括資訊訊息的Log.i()
、警示的Log.w()
和Log.e()
錯誤訊息。 - 記錄
tag
,(第一個參數),在本例中為"MainActivity"
。這個標記是字串,可讓您在 Logcat 中輕鬆找到您的記錄訊息。標記通常是類別的名稱。 - 實際記錄訊息,稱為
msg
(第二個參數),是簡短字串,在本例中為"onCreate Called"
。
- 編譯並執行 DessertClicker 應用程式。輕觸甜點時,不會在應用程式中看到任何行為差異。在 Android Studio 中,按一下螢幕底部的Logcat分頁標籤。
- 在「Logcat」視窗的搜尋欄位中輸入
MainActivity
。
Logcat 可包含許多訊息,其中大部分為不適用訊息。您可以透過多種方式篩選 Logcat 項目,但搜尋是最簡單的方法。由於您在程式碼中使用 MainActivity
做為記錄標記,因此您可以使用該標記篩選記錄。在搜尋字詞開頭加上 D/
,表示只會篩選由 Log.d()
所建立的偵錯訊息。您的記錄訊息包括日期和時間、檔案包名稱 (com.example.dessertclicker
)、記錄標記 (開頭為 D/
),以及實際訊息。由於這則訊息會出現在記錄中,但您知道系統已執行該 onCreate()
。
您也可以使用搜尋列旁的下拉式選單,依層級篩選記錄。如要執行相同搜尋,請在下拉式選單中選取「Debug」並輸入相同的查詢字串。
步驟 2:實作 onStart()
方法
系統將在 onCreate()
之後呼叫 onStart()
生命週期方法。onStart()
開始執行後,螢幕上會顯示您的活動。取消喜歡onCreate()
,系統僅會呼叫一次來初始化活動,在活動生命週期中,系統可能會多次呼叫 onStart()
。
請注意,onStart()
和對應的 onStop()
生命週期方法配對。如果使用者啟動應用程式,然後返回裝置的主畫面,活動就會停止,且不再顯示於螢幕上。
- 在 Android Studio,於
MainActivity.kt
開啟且游標位於MainActivity
類別內時選取「Code」(程式碼) >「Override Methods」(覆寫方法),或按一下Control+O
。顯示的對話方塊會列出您可在此類別中覆寫的所有方法。
- 開始輸入
onStart
以搜尋正確方法。如要捲動至下一個相符的項目,請使用向下鍵。從清單中選擇onStart()
,然後按一下確定,以插入樣板覆寫程式碼。程式碼如下所示:
override fun onStart() {
super.onStart()
}
- 在
onStart()
方法中加入記錄訊息:
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart Called")
}
- 編譯並執行 DessertClicker 應用程式,然後開啟Logcat窗格。
- 在搜尋欄位中輸入
MainActivity
,以篩選記錄。請注意,系統將逐一呼叫onCreate()
和onStart()
方法,且您的活動會顯示在螢幕上。 - 按下裝置的主畫面按鈕,然後使用最近使用畫面返回活動。請注意,活動會從上次中斷的地方接續進行,且全都使用相同的值,同時系統會將
onStart()
再次記錄到 Logcat。另請注意,通常不會再次呼叫onCreate()
方法。
2022-07-12 08:11:29.216 16346-16346/com.example.dessertclicker D/MainActivity: onCreate Called 2022-07-12 08:11:29.344 16346-16346/com.example.dessertclicker D/MainActivity: onStart Called 2022-07-12 08:11:42.585 16346-16346/com.example.dessertclicker D/MainActivity: onStart Called
步驟 3:新增更多記錄陳述式
在這個步驟中,您會實作所有其他生命週期方法的記錄功能。
- 覆寫
MainActivity
中的其餘生命週期方法,並為每個方法新增記錄陳述式,如以下程式碼所示:
override fun onResume() {
super.onResume()
Log.d(TAG, "onResume Called")
}
override fun onRestart() {
super.onRestart()
Log.d(TAG, "onRestart Called")
}
override fun onPause() {
super.onPause()
Log.d(TAG, "onPause Called")
}
override fun onStop() {
super.onStop()
Log.d(TAG, "onStop Called")
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy Called")
}
- 再次編譯並執行 Dessert Clicker,並檢查 Logcat。
請注意,除了 onCreate()
和 onStart()
以外,這次系統也會提供 onResume()
生命週期回呼的記錄訊息。
2022-07-12 08:16:13.356 16421-16421/com.example.dessertclicker D/MainActivity: onCreate Called 2022-07-12 08:16:13.424 16421-16421/com.example.dessertclicker D/MainActivity: onStart Called 2022-07-12 08:16:13.426 16421-16421/com.example.dessertclicker D/MainActivity: onResume Called
活動從頭開始時,系統會依序呼叫所有三個生命週期回呼:
onCreate()
當系統建立應用程式時。onStart()
會在螢幕上顯示應用程式,但使用者還無法與該應用程式互動。onResume()
會將應用程式移至前景,而使用者現在可以與應用程式互動。
儘管有名稱,即使沒有可繼續進行的操作,啟動時仍會呼叫 onResume()
方法。
4. 探索生命週期用途
您已經設定 Dessert Clicker 應用程式進行記錄,現在您可以開始使用該應用程式,並探索觸發生命週期回呼的方式。
用途 1:開啟及關閉活動
您將從最基本的用途開始,也就是初次啟動應用程式後,關閉應用程式。
- 編譯並執行 Dessert Clicker 應用程式 (如果尚未執行)。如您所見,活動初次開始時,就會呼叫
onCreate()
、onStart()
,以及onResume()
回呼。
2022-07-12 08:30:20.171 16656-16656/com.example.dessertclicker D/MainActivity: onCreate Called 2022-07-12 08:30:20.236 16656-16656/com.example.dessertclicker D/MainActivity: onStart Called 2022-07-12 08:30:20.239 16656-16656/com.example.dessertclicker D/MainActivity: onResume Called
- 輕觸杯子蛋糕數次。
- 輕觸裝置上的返回按鈕。
請注意,Logcat 中會依序呼叫 onPause()
和 onStop()
。
2022-07-12 08:31:18.729 16656-16656/com.example.dessertclicker D/MainActivity: onPause Called 2022-07-12 08:31:19.301 16656-16656/com.example.dessertclicker D/MainActivity: onStop Called
在此情況下,使用「Back」按鈕會導致活動 (和應用程式) 從畫面移除,並移至活動堆疊的背面。
如果程式碼手動呼叫活動的 finish()
方法,或是使用者強制退出應用程式,Android OS 可能會關閉您的活動。例如,使用者可以在「最近使用」螢幕中強制退出或關閉應用程式。若應用程式長時間未處於螢幕上,作業系統也可能會自行關閉您的活動。Android 會藉此節省電池電力,並允許其他應用程式使用您的應用程式的資源。以上僅列舉 Android 系統刪除活動的原因。在某些其他情況下,Android 系統會刪除活動,但不會發出警告。
用途 2:離開後再返回活動
現在,您已啟動並關閉應用程式,您可看到活動首次建立時的大部分生命週期狀態。此外,您也會看到活動關閉時經歷過的大部分生命週期狀態。然而,當使用者與 Android 裝置互動時,其會於應用程式間切換、返回主螢幕、啟動新的應用程式,並處理因其他活動 (例如來電) 而中斷的活動。
每次使用者離開該活動時,活動都不會完全關閉:
- 當系統不再於螢幕中顯示活動時,即稱為使活動進入背景。反之,則活動位於前景或螢幕上。
- 使用者返回您的應用程式時,系統會重新啟動相同的活動,並再次顯示該活動。生命週期中的此部分稱為應用程式的可見生命週期。
當應用程式在背景運作時,通常不應主動運作,以節約系統資源和電池壽命。您會使用 Activity
生命週期及其回呼來瞭解應用程式移至背景的時間,以便暫停任何進行中的作業。接著您會在應用程式進入前景時重新開始作業。
在這個步驟中,您可以查看應用程式進入背景後再次回到前景的活動生命週期。
- 執行 Dessert Clicker 應用程式時,點選紙杯蛋糕數次。
- 按下裝置上的「主畫面」按鈕,然後觀察 Android Studio 中的 Logcat。返回主畫面會讓應用程式進入背景,而非完全關閉應用程式。請注意,系統會呼叫
onPause()
和onStop()
方法。
2022-07-12 11:49:48.593 18350-18350/com.example.dessertclicker D/MainActivity: onPause Called 2022-07-12 11:49:49.191 18350-18350/com.example.dessertclicker D/MainActivity: onStop Called
呼叫 onPause()
後,應用程式就不再有焦點。onStop()
後,應用程式就不會再顯示於螢幕上。儘管活動已經停止,但 Activity
物件仍位於背景的記憶體中。Android 作業系統尚未刪除活動。使用者可能會返回應用程式,因此 Android 會保留您的活動資源。
- 使用「Recents」畫面返回應用程式。在模擬器中,點選如下圖所示的正方形系統按鈕即可存取「Recents」畫面。
請注意,活動會在 Logcat 中使用 onRestart()
和 onStart()
重新啟動,然後使用 onResume()
重新啟用。
2022-07-12 11:50:54.787 18350-18350/com.example.dessertclicker D/MainActivity: onRestart Called 2022-07-12 11:50:54.789 18350-18350/com.example.dessertclicker D/MainActivity: onStart Called 2022-07-12 11:50:54.791 18350-18350/com.example.dessertclicker D/MainActivity: onResume Called
當活動返回前景時,就不會再次呼叫 onCreate()
方法。活動物件並未刪除,因此不需要重新建立。系統會呼叫 onRestart()
方法,而不是 onCreate()
。請注意,當活動返回前景時,系統會保留售出甜點數量。
- 至少啟動一個 Dessert Clicker 以外的應用程式,使裝置的最近使用螢幕中含有數個應用程式。
- 開啟最近使用螢幕,並開啟其他最近活動。接著返回最近使用的應用程式,並將 Dessert Clicker 移回前景。
請注意,此處 Logcat 中顯示的回呼與按下主畫面按鈕時相同。當應用程式進入背景時,系統會呼叫 onPause()
和 onStop()
,並在其返回時呼叫 onRestart()
、onStart()
和 onResume()
。
當應用程式停止並移至背景,或應用程式重新啟動並返回前景時,系統就會呼叫這些方法。如果遇到這類情況,而您必須在應用程式中執行工作,請覆寫相關的生命週期回呼方法。
用途 3:部分隱藏活動
您已經瞭解應用程式啟動且呼叫 onStart()
時,螢幕上會顯示該應用程式。呼叫 onResume()
時,應用程式會取得使用者焦點,意即使用者可與應用程式互動。應用程式完全位於螢幕上,且有使用者焦點的生命週期部分,稱為前景生命週期。
應用程式進入背景時,焦點會於 onPause()
後消失,且應用程式在 onStop()
後也不再顯示。
焦點和瀏覽權限之間的差異非常重要。活動可以部分顯示在螢幕上,但沒有使用者焦點。在此步驟中,可看到一種情況,即可部分顯示活動,但沒有使用者焦點。
- 執行 Dessert Clicker 應用程式後,按一下螢幕右上方的共用按鈕。
共用活動會顯示在螢幕的下半部,但活動仍會在上半部顯示。
- 檢查 Logcat,並且留意其中呼叫的只有
onPause()
。
2022-07-12 12:14:10.864 18350-18350/com.example.dessertclicker D/MainActivity: onPause Called
在此用途中,系統不會呼叫 onStop()
,因為活動仍部分顯示。不過,這類活動沒有使用者焦點,且使用者無法與其互動,因為位於前景的「分享」活動具有使用者焦點。
為什麼這個差異很重要?返回活動或前往其他活動/應用程式前,僅使用 onPause()
的干擾通常只會持續一小段時間。一般而言,建議您持續更新 UI,避免其餘應用程式發生凍結問題。
在 onPause()
中執行的程式碼會使其他內容無法顯示,因此請將程式碼保存在輕量 onPause()
中。例如,如果有來電,onPause()
中的程式碼可能會延遲來電通知。
- 按一下分享對話方塊以外的地方,返回應用程式,並留意系統已呼叫
onResume()
。
onResume()
和 onPause()
都必須與焦點有關。活動有焦點時,系統會呼叫 onResume()
方法,而活動失去聚焦時,就會呼叫 onPause()
。
5. 探索設定變更
除此之外,還有其他管理活動生命週期方面的重要須知,可協助您瞭解設定變更對活動生命週期的影響。
設定變更於裝置狀態改變時發生,因此基本上,使系統解決變更的最簡單方法就是完全關閉,然後重新建立活動。舉例來說,若使用者變更裝置語言,您必須調整整個版面配置,以配合不同的文字方向和字串長度。如果使用者將裝置插入座架或新增實體鍵盤,應用程式版面配置可能必須採用不同的顯示大小或版面配置。如果裝置螢幕方向改變 (例如將裝置從直向轉為橫向或向後旋轉),您可能需要根據新的螢幕方向變更版面配置。讓我們看看應用程式在這個情境中的行為。
最後示範的生命週期回呼為 onDestroy()
,也就是在 onStop()
之後呼叫。會在活動刪除前呼叫。如果應用程式的程式碼呼叫 finish()
,或是系統因設定變更而刪除並重新建立活動,就會發生這種情況。
設定變更導致必須呼叫 onDestroy()
螢幕旋轉是一種設定變更的類型,會導致關閉活動並重新啟動。如要模擬這項設定變更並檢查其影響,請完成下列步驟:
- 編譯並執行應用程式。
- 確保模擬器的螢幕旋轉鎖定功能已停用。
- 將裝置或模擬器旋轉至橫向模式。您可以使用旋轉按鈕向左或向右旋轉模擬器。
- 檢查 Logcat,瞭解在活動關閉時,系統會依序呼叫
onPause()
、onStop()
和onDestroy()
。
2022-07-16 20:03:31.147 30587-30587/com.example.dessertclicker D/MainActivity: onPause Called 2022-07-16 20:03:31.155 30587-30587/com.example.dessertclicker D/MainActivity: onStop Called 2022-07-16 20:03:31.184 30587-30587/com.example.dessertclicker D/MainActivity: onDestroy Called
裝置旋轉時資料遺失
- 編譯並執行應用程式,然後開啟 Logcat。
- 按數次杯子蛋糕,但請注意,售出甜點和總收益不為零。
- 確保模擬器的螢幕旋轉鎖定功能已停用。
- 將裝置或模擬器旋轉至橫向模式。您可以使用旋轉按鈕向左或向右旋轉模擬器。
- 檢查 Logcat 中的輸出內容。在
MainActivity
上篩選輸出內容。
2022-07-12 12:31:55.098 19326-19326/com.example.dessertclicker D/MainActivity: onCreate Called 2022-07-12 12:31:55.152 19326-19326/com.example.dessertclicker D/MainActivity: onStart Called 2022-07-12 12:31:55.154 19326-19326/com.example.dessertclicker D/MainActivity: onResume Called 2022-07-12 12:31:59.600 19326-19326/com.example.dessertclicker D/MainActivity: onPause Called 2022-07-12 12:31:59.608 19326-19326/com.example.dessertclicker D/MainActivity: onStop Called 2022-07-12 12:31:59.644 19326-19326/com.example.dessertclicker D/MainActivity: onDestroy Called 2022-07-12 12:31:59.668 19326-19326/com.example.dessertclicker D/MainActivity: onCreate Called 2022-07-12 12:31:59.678 19326-19326/com.example.dessertclicker D/MainActivity: onStart Called 2022-07-12 12:31:59.679 19326-19326/com.example.dessertclicker D/MainActivity: onResume Called
請注意,當裝置或模擬器旋轉螢幕時,系統會呼叫所有生命週期回呼來關閉活動。接著,當您重新建立活動時,系統會呼叫所有生命週期回呼來啟動活動。
裝置旋轉且關閉並重新建立活動後,活動就會以預設值重新啟動,也就是甜點圖片、已售出的甜點數量,以及總收益重設為零。
如要瞭解這些值重設的原因以及修正方式,您必須瞭解可組合元件的生命週期,以及其如何觀測及保留其狀態。
可組合元件的生命週期
應用程式的 UI 最初是透過名為 Composition 的程序執行可組合函式建立而成。
應用程式的狀態變更時,系統會安排重新組成排程。重新組成是指,當 Compose 重新執行可組合函式時,其狀態可能已變更,並建立了更新後的 UI。Composition 已更新以反映這些變更。
建立或更新 Composition 的唯一方法就是其初始組成和後續的重組。
可組合函式有自己的生命週期,與活動生命週期無關。其生命週期由事件組成:進入 Composition,重組 0 次以上,然後離開 Composition。
為了讓 Compose 追蹤及觸發重新組成,必須瞭解狀態何時發生變化。如要向 Compose 表明其應追蹤物件的狀態,則該物件的類型必須為 State
或 MutableState
。State
類型不可變動,且只能讀取。MutableState
類型可變動,並允許讀取及寫入。
您已在先前的程式碼研究室的 Lemonade 應用程式和 Tip Time 應用程式中看過及使用 MutableState
。
如要建立可變動的變數 revenue
,請使用 mutableStateOf
進行宣告。0
是其初始預設值。
var revenue = mutableStateOf(0)
雖然足以讓 Compose 在收益值變更時觸發重組,但並不足以保留更新後的值。每次重新執行可組合元件時,都會將收益值重新初始化為 0
的初始預設值
如要指示 Compose 在重組期間保留並重複使用這個值,則必須使用 remember
API 宣告。
var revenue by remember { mutableStateOf(0) }
如果 revenue
的值有所變更,Compose 會安排所有可讀取這個值的可組合函式以進行重組。
雖然 Compose 會在重組期間記住收益狀態,但在設定變更期間不會保留此狀態。為了讓 Compose 在設定變更期間保留狀態,您必須使用 rememberSaveable
。
如需其他做法和相關資訊,請參考「Compose 中的狀態簡介」程式碼研究室。
使用 rememberSaveable
在設定變更期間儲存值
如果 Android OS 刪除並重新建立活動,您會使用 rememberSaveable
函式儲存您需要的值。
如要在重組期間儲存值,您必須使用 remember
。在重組「和」設定變更期間使用 rememberSaveable
來儲存值。
使用 rememberSaveable
儲存值可確保在還原活動時可用 (如需要)。
- 在
MainActivity
中,將目前使用remember
的 5 個變數群組更新為rememberSaveable
。
var revenue by remember { mutableStateOf(0) }
...
var currentDessertImageId by remember {
mutableStateOf(desserts[currentDessertIndex].imageId)
}
var revenue by rememberSaveable { mutableStateOf(0) }
...
var currentDessertImageId by rememberSaveable {
mutableStateOf(desserts[currentDessertIndex].imageId)
}
- 編譯並執行應用程式。
- 按數次杯子蛋糕,但請注意,售出甜點和總收益不為零。
- 將裝置或模擬器旋轉至橫向模式。
- 請注意,在活動刪除並重新建立活動之後,甜點圖片、售出甜點和總收益都會還原為先前的值。
6. 解決方案程式碼
7. 摘要
活動生命週期
- 活動生命週期是一組活動轉移的狀態。活動生命週期是從 Android 作業系統首次建立活動時開始,並在 OS 刪除活動時結束。
- 使用者在活動間及應用程式內外瀏覽時,每個活動會在活動生命週期的各個狀態間移動。
- 活動生命週期中的每個狀態都有相應的回呼方法,可在
Activity
類別中覆寫。生命週期方法的核心組合如下:onCreate()
、onRestart()
、onStart()
、onResume()
、onPause()
、onStop()
、onDestroy()
。 - 如要新增在活動轉換為生命週期狀態時發生的行為,請覆寫狀態的回呼方法。
- 如要在 Android Studio 中為類別新增架構覆寫方法,請選取程式碼 > 覆寫方法,或按下
Control+O
。
使用記錄檔進行記錄
- Android Logging API (尤其是
Log
類別),可讓您編寫在 Android Studio 的 Logcat 中顯示的簡短訊息。 - 請使用
Log.d()
編寫偵錯訊息。這個方法使用兩個引數:記錄標記,通常是類別名稱,以及記錄訊息,此為簡短字串。 - 使用 Android Studio 中的「Logcat」視窗檢視系統記錄,包括您編寫的訊息。
設定變更
- 設定變更於裝置狀態改變時發生,因此基本上,使系統解決變更的最簡單方法就是刪除,然後重新建立活動。
- 最常見的設定變更範例為,使用者將裝置從直向轉為橫向模式,或從橫向轉為直向模式時。當裝置語言變更或使用者在硬體鍵盤中附加時,也可能會發生設定變更。
- 發生設定變更時,Android 會叫用所有活動生命週期的關閉回呼。接著,Android 會從頭重新啟動活動,並執行所有生命週期啟動回呼。
- Android 因設定變更而關閉應用程式時,Android 會以
onCreate()
重新啟動活動。 - 如果想儲存需要在設定變更後繼續保留的值,需以
rememberSaveable
宣告其變數。