注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術(shù)一般,由于喜愛安卓而產(chǎn)生了翻譯的念頭,純屬個人興趣愛好。
原文鏈接: http://developer.android.com/training/basics/activity-lifecycle/recreating.html
在應(yīng)用被正常使用的情況下,會有一些場景發(fā)生并使得你的activity被銷毀,比如:當(dāng)用戶按下了返回鍵,或者你的activity調(diào)用了
finish()
方法將自己銷毀。當(dāng)你的
activity
處于停止態(tài)且已經(jīng)很久沒有被使用的情況下,系統(tǒng)也會將它銷毀。還有一種情況是處于前臺的
activity
需要更多的資源,此時系統(tǒng)必須將一部分后臺進(jìn)程停止來釋放出一些內(nèi)存空間。
當(dāng)你的activity因為用戶按下了返回鍵或者自己調(diào)用了finish()將自己銷毀時,該 Activity 的實例將不再存在,因為導(dǎo)致其被銷毀的行為暗示了這個activity已經(jīng)不再需要了。然后如果是由于系統(tǒng)資源緊張而被迫將Activity銷毀(非正常的應(yīng)用行為),那么雖然 Activity 的實例已經(jīng)不再了,當(dāng)用戶回到這個 Activity 時,系統(tǒng)仍然會記得它其實是存在的。此時,系統(tǒng)會利用該 Activity 被銷毀時所保存的描述其狀態(tài)的數(shù)據(jù)集,來創(chuàng)建一個新的 Activity 實例。這些系統(tǒng)用來恢復(fù)之前狀態(tài)的數(shù)據(jù)被稱作為“ 實例狀態(tài)(instance state) ”,它實質(zhì)上是一個存儲于一個 Bundle 對象的鍵值對數(shù)據(jù)集合。
Caution:
每次用戶旋轉(zhuǎn)了屏幕后,你的activity都會被銷毀和重新創(chuàng)建。這樣做的原因是因為屏幕的旋轉(zhuǎn)會導(dǎo)致屏幕參數(shù)的變化(長和寬互換),此時你的activity可能需要加載一些可選的資源(比如針對于橫屏或豎屏下的布局)
默認(rèn)的,系統(tǒng)使用 Bundle 實例狀態(tài) 來保存你的activity布局中每個 View 對象的信息(比如在 EditText 對象中輸入的文字)。所以,如果你的activity實例被銷毀和重新創(chuàng)建,布局的狀態(tài)會恢復(fù)到之前的狀態(tài),且你不需要為此編寫代碼。然而,你的activity可能會有更多你希望存儲的狀態(tài)信息,比如一些用來追蹤用戶進(jìn)度的成員變量。
Note:
為了讓Android系統(tǒng)恢復(fù)activity中的view狀態(tài), 每個View必須有一個獨有的ID ,這個ID由屬性字段“
android:id
”提供。
為了存儲更多關(guān)于activity狀態(tài)的數(shù)據(jù),你必須覆寫 onSaveInstanceState() 回調(diào)函數(shù)。當(dāng)用戶離開你的activity時系統(tǒng)會調(diào)用該方法,并且傳遞給他一個 Bundle 對象,存儲數(shù)據(jù)以防activity被意外地銷毀了。之后如果系統(tǒng)必須重新創(chuàng)建這個activity實例,它會把相同的 Bundle 對象傳遞給 onRestoreInstanceState() 方法和 onCreate() 方法。
圖1. 當(dāng)系統(tǒng)要停止你的activity時,它會調(diào)用 onSaveInstanceState() 方法(1),所以你可以指定你先要存儲的額外數(shù)據(jù),當(dāng)activity被重新創(chuàng)建時會用到它們。 如果activity被銷毀了同時這個activity實例需要重新創(chuàng)建,系統(tǒng)會將(1)中定義的數(shù)據(jù)傳遞給 onCreate() 方法(2),以及 onRestoreInstanceState() 方法(3)
?
一). 保存你的Activity狀態(tài)
當(dāng)你的activity將要停止,系統(tǒng)會調(diào)用 onSaveInstanceState() 方法這樣你的activity會通過鍵值對的形式將狀態(tài)信息保存起來。這個方法的默認(rèn)實現(xiàn)會保存activity的 view狀態(tài),比如一個 EditText 控件內(nèi)的文本信息或者 ListView 當(dāng)前滑動到的位置信息。
為了為你的activity保存額外的狀態(tài)信息,你必須實現(xiàn) onSaveInstanceState() 方法,并且將鍵值對添加到 Bundle 對象中。例如:
static final String STATE_SCORE = "playerScore" ; static final String STATE_LEVEL = "playerLevel" ; ... @Override public void onSaveInstanceState(Bundle savedInstanceState) { // Save the user's current game state savedInstanceState.putInt(STATE_SCORE, mCurrentScore); savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel); // Always call the superclass so it can save the view hierarchy state super .onSaveInstanceState(savedInstanceState); }
Caution:
必須調(diào)用父類的 onSaveInstanceState() ,這樣默認(rèn)的實現(xiàn)會保存View的狀態(tài)
?
二). 恢復(fù)你的Activity狀態(tài)
當(dāng)你的Activity在之前被銷毀后需要被重新創(chuàng)建時,你可以通過系統(tǒng)傳遞給Activity的 Bundle 對象來恢復(fù)之前的狀態(tài)。 onRestoreInstanceState() 方法和 onCreate() 方法都會接受到相同的 Bundle 對象,其中包含了實例的狀態(tài)信息。
因為不管是系統(tǒng)在創(chuàng)建一個新的實例還是重新創(chuàng)建一個舊的, onCreate() 都會被系統(tǒng)調(diào)用,所以在你嘗試讀取 Bundle 之前,必須檢查它是否是null。如果是null,那么系統(tǒng)會創(chuàng)建一個新的activity實例,而不是進(jìn)行恢復(fù)。
下面就是你將如何在 onCreate() 中恢復(fù)狀態(tài)的例子:
@Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); // Always call the superclass first // Check whether we're recreating a previously destroyed instance if (savedInstanceState != null ) { // Restore value of members from saved state mCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); } else { // Probably initialize members with default values for a new instance } ... }
除了在 onCreate() 恢復(fù)狀態(tài),你還可以選擇實現(xiàn) onRestoreInstanceState() ,這個方法在系統(tǒng)調(diào)用了 onStart() 方法之后被調(diào)用。僅當(dāng)有可以用來恢復(fù)的以保存數(shù)據(jù)存在是,系統(tǒng)才會調(diào)用 onRestoreInstanceState() ,所以你不需要判斷 Bundle 是否是null:
public void onRestoreInstanceState(Bundle savedInstanceState) { // Always call the superclass so it can restore the view hierarchy super .onRestoreInstanceState(savedInstanceState); // Restore state members from saved instance mCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); }
Caution:
必須調(diào)用父類的 onRestoreInstanceState() ,這樣默認(rèn)的實現(xiàn)會恢復(fù)View的狀態(tài)
如果想要學(xué)習(xí)關(guān)于在運(yùn)行時由于重啟事件導(dǎo)致activity被重新創(chuàng)建(如旋轉(zhuǎn)了屏幕),可以閱讀: Handling Runtime Changes
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
