天天看點

activity狀态儲存講解一

一、臨時性資料

首先說明一下一般控件的狀态是不需要你寫代碼去儲存的,因為Android架構中幾乎所有UI控件都實作了onSaveInstanceState方法, 是以當Activity銷毀和重建時, 這些UI控件會自動儲存和恢複狀态資料。當然你也不能什麼都不做,你需要為這些控件指定一個id,剩下的事情架構會自己去做,如果你不指定id,那麼控件的狀态資料是不會自動儲存和恢複的。

下面來詳細說明一下onSaveInstanceState和onRestoreInstanceState這兩個方法。

onSaveInstanceState調用的原則是系統有未經你的許可銷毀Activity的可能。那麼onSaveInstanceState有下面幾種情況會調用:

1、按下HOME鍵(onPause-->onStop-->onStart-->onResume)  

2、長按HOME鍵切換到了其他APP(onPause-->onStop-->onStart-->onResume)  

3、橫豎屏切換(onPause-->onStop-->onDestroy-->onCreate-->onStart-->onResume)  

4、Activity的導航(onPause-->onStop-->onStart-->onResume)  

5、鎖定螢幕(鎖定:onPause-->onStop,喚醒:onStart-->onResume)

onRestoreInstanceState被調用的原則是Activity被銷毀了,而不是可能被銷毀了。

二、持久性資料

在onResume和onPause方法中做,可以把資料儲存在資料庫或者SharedPreference中。然而在生命周期函數中不适合做耗時的操作,讀者如果有好的方法儲存較大的資料,歡迎評論。

一般來說, 調用onPause()和onStop()方法後的activity執行個體仍然存在于記憶體中, activity的所有資訊和狀态資料不會消失, 當activity重新回到前台之後, 所有的改變都會得到保留. 

但是當系統記憶體不足時, 調用onPause()和onStop()方法後的activity可能會被系統摧毀, 此時記憶體中就不會存有該activity的執行個體對象了. 如果之後這個activity重新回到前台, 之前所作的改變就會消失. 為了避免此種情況的發生, 開發者可以覆寫onSaveInstanceState()方法. onSaveInstanceState()方法接受一個Bundle類型的參數, 開發者可以将狀态資料存儲到這個Bundle對象中, 這樣即使activity被系統摧毀, 當使用者重新啟動這個activity而調用它的onCreate()方法時, 上述的Bundle對象會作為實參傳遞給onCreate()方法, 開發者可以從Bundle對象中取出儲存的資料, 然後利用這些資料将activity恢複到被摧毀之前的狀态.

Java代碼  

activity狀态儲存講解一
  1. <span style="font-size: small;">public class MainActivity extends Activity {  
  2.     public static final int SECOND_ACTIVITY = 0;  
  3.     private String temp;  
  4.     @Override  
  5.     public void onCreate(Bundle savedInstanceState) {  
  6.         super.onCreate(savedInstanceState);  
  7.         // 從savedInstanceState中恢複資料, 如果沒有資料需要恢複savedInstanceState為null  
  8.         if (savedInstanceState != null) {  
  9.             temp = savedInstanceState.getString("temp");  
  10.             System.out.println("onCreate: temp = " + temp);  
  11.         }  
  12.     }  
  13.     public void onResume() {  
  14.         super.onResume();  
  15.         temp = "xing";  
  16.         System.out.println("onResume: temp = " + temp);  
  17.         // 切換螢幕方向會導緻activity的摧毀和重建  
  18.         if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {  
  19.             setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);  
  20.             System.out.println("螢幕切換");  
  21.         }  
  22.     }  
  23.     // 将資料儲存到outState對象中, 該對象會在重建activity時傳遞給onCreate方法  
  24.     @Override  
  25.     protected void onSaveInstanceState(Bundle outState) {  
  26.         super.onSaveInstanceState(outState);  
  27.         outState.putString("temp", temp);  
  28.     }  
  29. }</span>  

需要注意的是, onSaveInstanceState()方法并不是一定會被調用的, 因為有些場景是不需要儲存狀态資料的. 比如使用者按下BACK鍵退出activity時, 使用者顯然想要關閉這個activity, 此時是沒有必要儲存資料以供下次恢複的, 也就是onSaveInstanceState()方法不會被調用. 如果調用onSaveInstanceState()方法, 調用将發生在onPause()或onStop()方法之前. 

onSaveInstanceState()方法的預設實作

如果開發者沒有覆寫onSaveInstanceState()方法, 此方法的預設實作會自動儲存activity中的某些狀态資料, 比如activity中各種UI控件的狀态. android應用架構中定義的幾乎所有UI控件都恰當的實作了onSaveInstanceState()方法, 是以當activity被摧毀和重建時, 這些UI控件會自動儲存和恢複狀态資料. 比如EditText控件會自動儲存和恢複輸入的資料, 而CheckBox控件會自動儲存和恢複選中狀态. 開發者隻需要為這些控件指定一個唯一的ID(通過設定android:id屬性即可), 剩餘的事情就可以自動完成了. 如果沒有為控件指定ID, 則這個控件就不會進行自動的資料儲存和恢複操作.

由上所述, 如果開發者需要覆寫onSaveInstanceState()方法, 一般會在第一行代碼中調用該方法的預設實作: super.onSaveInstanceState(outState).

是否需要覆寫onSaveInstanceState()方法

既然該方法的預設實作可以自動的儲存UI控件的狀态資料, 那什麼時候需要覆寫該方法呢?

如果需要儲存額外的資料時, 就需要覆寫onSaveInstanceState()方法. 如需要儲存類中成員變量的值(見上例).

onSaveInstanceState()方法适合儲存什麼資料

由于onSaveInstanceState()方法方法不一定會被調用, 是以不适合在該方法中儲存持久化資料, 例如向資料庫中插入記錄等. 儲存持久化資料的操作應該放在onPause()中. onSaveInstanceState()方法隻适合儲存瞬态資料, 比如UI控件的狀态, 成員變量的值等.

引發activity摧毀和重建的其他情形

除了系統處于記憶體不足的原因會摧毀activity之外, 某些系統設定的改變也會導緻activity的摧毀和重建. 例如改變螢幕方向(見上例), 改變裝置語言設定, 鍵盤彈出等.

繼續閱讀