我在做日志模塊的時候,日志使用 static 單例,但是需要初始化傳入一些基本數據,我把這個初始化的步奏寫在 FlashActivity 里了,然后在后臺老是收到日志靜態對象的空指針異常,找了很久才發現問題所在
首先明確一下 static 變量的生命周期 = 整個進程的生命周期,進程在 static 在,進程死 static 回收
平時我們游一個場景如下:app home 切到后臺,長時間后 app 進程被系統回收掉,然后我們喚起這個 app ,這時 app 進程會重新啟動,但是頁面的啟動不會走默認的流程,而是會直接打開上次離開時的頁面,所以我這個執行初始化的 FlashActivity 沒機會跑了,所以這個 static 變量就會為 null,這種情況是進程被系統回收之后才會出現的,我們自己關閉進程沒事
再次強調一下,static 存儲在 method area 區,不再堆內存中,要是 static 對象也被回收,那么說明進程頁跟著一起死了,換句話說,要回收 static 就必須殺進程。明確了這一點,我們只要把我們的初始化方法想辦法寫在 application 的 onCreate 里就行,即使進程死了,static 對象能保證正常初始化就行。
那么我們怎么應對呢:
- 頁面級別處理
我們可以利用activity 的 onSaveInstanceState 機制,onSaveInstanceState 存儲的數據保存在系統進程,會為我們保存優先的幾個小時,時間長了一樣會被回收掉
@Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
outState.putString("aa", MyActivityManager.aa);
outState.putString("bb", MyActivityManager.bb);
outState.putString("username", MyActivityManager.username);
// Log.i("OK","onSaveInstanceState");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onRestoreInstanceState(savedInstanceState);
MyActivityManager.aa=savedInstanceState.getString("aa");
MyActivityManager.bb=savedInstanceState.getString("bb");
MyActivityManager.username=savedInstanceState.getString("username");
// Log.i("OK","onRestoreInstanceState");
}
利用 application
進程沒有,再被重新啟動,那么 application 對象一定會被重新初始化,我們可以考慮把初始化的代寫到 application 的 onCreate 中,一定會被執行的低內存時,手動殺死進程
我們監聽系統的內存回收狀態,發現進程快被殺死了,我們干脆自己把進程殺了,不被系統機會,下次進程再創建就不會再打開離開時的頁面了。
/**
* 內存不夠時
* @param level
*/
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (level == TRIM_MEMORY_MODERATE) {
((TMDApplication) getApplication()).destroyAllData(null);
}
}
level 有幾個級別:
- TRIM_MEMORY_COMPLETE:
內存不足,并且該進程在后臺進程列表最后一個,馬上就要被清理 - TRIM_MEMORY_MODERATE:
內存不足,并且該進程在后臺進程列表的中部。 - TRIM_MEMORY_BACKGROUND:
內存不足,并且該進程是后臺進程。 - TRIM_MEMORY_UI_HIDDEN:
內存不足,并且該進程的UI已經不可見了
TRIM_MEMORY_COMPLETE這個監聽的時候有時候監聽不到,建議監聽TRIM_MEMORY_MODERATE,在這個里面處理退出程序操作。
一些資料
- static 聲明周期:Android靜態變量的生命周期