一、紅米Note上頻繁NullPointException
繼解決了Fragment中使用getActivity()返回null的問題後,在測試中又發現,在紅米Note上離開程序後從後臺返回時經常Crash,錯誤仍然是NullPointException。。。
項目需求是要求先登錄,在LoginActivity登錄完畢獲取到Token後,我直接用Intent傳給了主界面MainActivity再進行後續操作。但是當程序後臺被殺掉後再恢復時,雖然會重新執行MainActivity的onCreate()
,但是Intent內的數據卻不會再有,我取出Token後沒有做判斷就使用,於是就拋出了NullPointException。
紅米系列內存比較小,App切換到後臺以後極易被幹掉,所以這個問題在紅米Note上比較容易重現。
二、保存
錯誤的原因在於沒有緩存Intent傳入的數據,那我們就緩存一下好了。
最簡單的辦法莫過於寫入SharedPreference了,存入取出都很方便:
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
// 存入數據
sp.edit().putString("token", token).apply();
// 取出數據
String token = sp.getString("token", null);
但是sp只適合存放少量的數據,若需要緩存的數據稍複雜一點用sp就會很麻煩,另一種辦法是用數據庫緩存,但數據庫緩存代碼量比較大,改動也不是很方便。
其實,Android已經考慮到了這種問題,提供了一種系統級的界面緩存數據的方法,即InstanceState機制。
三、利用Android的InstanceState機制
我們可以看到,在Activity的onCreate()
方法是帶參數的:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
同時,Activity還帶有兩個方法:onSaveInstanceState()
和onRestoreInstanceState()
:
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()並不是生命週期方法。
它們不同於 onCreate()、onPause()等生命週期方法,它們並不一定會被觸發。當應用遇到意外情況(如:內存不足、用戶直接按Home鍵)由系統銷燬一個Activity時,onSaveInstanceState()會被調用。
但是當用戶主動去銷燬一個Activity時,例如在應用中按返回鍵,onSaveInstanceState()就不會被調用。因爲在這種情況下,用戶的行爲決定了不需要保存Activity的狀態。
通常onSaveInstanceState()只適合用於保存一些臨時性的狀態,而onPause()適合用於數據的持久化保存。
因此,在InstanceState內保存數據的方法類似SP,非常簡單:
@Override
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("token", token);
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
token = savedInstanceState.getString("token");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 你也可以在onCreate()裏恢復數據
// 但這樣做需要判斷恢復的數據出來是否爲null
token = savedInstanceState.getString("token");
}
這樣,在後臺內存不足程序被回收時,會自動緩存數據,下次進入時自動恢復就不會拋出異常了。
參考
本文首發http://www.dss886.com,轉載請註明