android static 變量丟失的處理

我在做日志模塊的時候,日志使用 static 單例,但是需要初始化傳入一些基本數據,我把這個初始化的步奏寫在 FlashActivity 里了,然后在后臺老是收到日志靜態對象的空指針異常,找了很久才發現問題所在

首先明確一下 static 變量的生命周期 = 整個進程的生命周期,進程在 static 在,進程死 static 回收

平時我們游一個場景如下:app home 切到后臺,長時間后 app 進程被系統回收掉,然后我們喚起這個 app ,這時 app 進程會重新啟動,但是頁面的啟動不會走默認的流程,而是會直接打開上次離開時的頁面,所以我這個執行初始化的 FlashActivity 沒機會跑了,所以這個 static 變量就會為 null,這種情況是進程被系統回收之后才會出現的,我們自己關閉進程沒事


系統殺死進程后執行
JVM的結構圖

再次強調一下,static 存儲在 method area 區,不再堆內存中,要是 static 對象也被回收,那么說明進程頁跟著一起死了,換句話說,要回收 static 就必須殺進程。明確了這一點,我們只要把我們的初始化方法想辦法寫在 application 的 onCreate 里就行,即使進程死了,static 對象能保證正常初始化就行。

那么我們怎么應對呢:

  1. 頁面級別處理
    我們可以利用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");  
        }  
  1. 利用 application
    進程沒有,再被重新啟動,那么 application 對象一定會被重新初始化,我們可以考慮把初始化的代寫到 application 的 onCreate 中,一定會被執行的

  2. 低內存時,手動殺死進程
    我們監聽系統的內存回收狀態,發現進程快被殺死了,我們干脆自己把進程殺了,不被系統機會,下次進程再創建就不會再打開離開時的頁面了。

    /**
     * 內存不夠時
     * @param level
     */
    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        if (level == TRIM_MEMORY_MODERATE) {
            ((TMDApplication) getApplication()).destroyAllData(null);
        }
    }

level 有幾個級別:


level 級別
  • TRIM_MEMORY_COMPLETE:
    內存不足,并且該進程在后臺進程列表最后一個,馬上就要被清理
  • TRIM_MEMORY_MODERATE:
    內存不足,并且該進程在后臺進程列表的中部。
  • TRIM_MEMORY_BACKGROUND:
    內存不足,并且該進程是后臺進程。
  • TRIM_MEMORY_UI_HIDDEN:
    內存不足,并且該進程的UI已經不可見了

TRIM_MEMORY_COMPLETE這個監聽的時候有時候監聽不到,建議監聽TRIM_MEMORY_MODERATE,在這個里面處理退出程序操作。

一些資料


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容