2014-03-30 52 views
1

我有一個列表活動,它執行常用列表活動類型的東西。所有的活動設置的正在於onCreate()方法如何判斷活動狀態是否已被破壞並需要重新創建

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_list_streams); 
    Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this)); 
    mActionBar = getActionBar(); 
    mStreamListAdapter = new StreamListRowAdapter(this, R.layout.stream_list_row); 
    mStreamListView = (ListView)findViewById(android.R.id.list); 
    mStreamListView.setAdapter(mStreamListAdapter); 
} 

做我沒有onStart()onResume()覆蓋。基於按下的菜單按鈕,我可以成功導出此活動,然後返回到此活動。當我通過startActivity(newIntent)離開此列表活動時,我沒有打電話結束,但是當回到此列表活動時,我確實在newIntent活動中致電完成。一切工作正常,除非ListActivity本身或其中一個新的活動已經坐在後臺很長一段時間(即我切換到另一個應用程序)。長時間以小時計量。有時(並非總是),當延遲後我回到應用程序時,列表活動不會顯示列表,菜單也不會顯示,只是在ActionBar中顯示活動標題的空白屏幕。

我意識到我需要通過onResume()(也許onStart())處理回到列表活動。但onResume()總是在導航回到此列表活動後調用,我如何才能真正知道表示ListAdapterListView的變量是否已被操作系統實際銷燬並需要在onResume()內重新創建,我不想重新創建它們每調用一次onResume()。我可以檢查它們是否等於空嗎?這很難測試,因爲這不會非常有規律地發生。

謝謝你, 加里

+0

你如何處理未捕獲的異常?如何試圖刪除線'Thread.setDefaultUncaughtExceptionHandler(新的ExceptionHandler(this));'?我想,如果你這樣做,你會在你描述的用例中得到一個異常,這將澄清你的'活動'有什麼問題。您只需要調查logcat條目 – Drew

回答

0

這聽起來像你缺少關於Android和活動的整個生命週期的一些基本信息。首先,我想提一下Android如何保存它的狀態。這裏有兩個要點。當離開一個活動是在被破壞的風險,它調用鉤子方法

@Override 
protected void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    outState.putInt("myKey1", 1); 
    outState.putString("myStringKey", "hello"); 
} 

當這個被稱爲,這是爲您節省一切,你想堅持的數據的機會。這可能是ID,字符串,陣列列表和幾乎任何其他類型的數據。

現在您已經保存了數據,在Activity的onCreate方法中,您將返回所有這些值。

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
      if (savedInstanceState != null) { 
       String myStr = savedInstanceState.getString("myStringKey"); 
       int myInt = savedInstanceState.getInt("myKey1", -1); 
      } 
      // do the rest of your setup 

} 

第一次onCreate被調用savedInstanceState爲null。要回答你的問題:「我怎麼才能知道表示ListAdapter和ListView的變量是否真的被操作系統銷燬了?」這就是你可以知道的。如果savedInstanceState不爲null,那麼您的東西可能已被銷燬。不過,我會說,無論如何,OnCreate被調用時,Activity已經被完全銷燬。

我會提到的另一件事情是,只要需要回收一些內存,Android就可以殺死你的後臺活動。當它這樣做時,它會爲你調用onSaveInstanceState方法。 Android不必在應用程序的「第一個」或「主要」屏幕上重新啓動應用程序。如果這是用戶離開的地方,它可以從幾個活動開始。我之所以提到這一點,是因爲它聽起來像是當Android決定在清除內存後創建活動時遇到問題。確保您的應用程序正常工作的最佳方式是隻需旋轉手機。將手機從橫向旋轉到橫向和/或向後移動會導致活動被銷燬,並使用onSaveInstanceState重新創建,然後傳回onCreate。根據您提供的信息,這是我現在可以提出的最佳選擇。

乾杯。

+0

因此,檢查Activity類的變量(ListView和ListAdapter)是否在onResume()內設置爲null不足以確定是否需要重新創建相應的對象?這是我最近嘗試解決這個問題,似乎沒有任何區別。我會在今晚嘗試你的建議,看看它是否能解決問題。謝謝。 –

0

我終於明白髮生了什麼事。我有2個活動,ActivityA和ActivityB以及一個Application對象。應用程序啓動後,ActivityA將初始化存儲在Application對象中的一些全局變量,然後啓動ActivityB。當我的應用長時間在後臺重啓後,應用的onCreate()被調用,然後調用ActivityB的onCreate()。 ActivityB依賴於Application對象中通常由ActivityA初始化的變量,但此時從未調用過ActivityA,並且全局變量未初始化。我仍然不清楚爲什麼ActivityA只是掛起了,而不是用一些消息說明變量是空的,這是Application對象中的onCreate()所設置的,但無論如何,當我發生這種情況時,我需要返回到ActivityA(),並在應用程序啓動時按照通常情況重新初始化所有內容。

我現在在Application對象中有一個布爾值,它指示在調用Application對象的onCreate()之後是否已經執行了ActivityA。 ActivityB檢查這個布爾標誌,如果沒有設置,那麼只需啓動ActivityA來執行啓動類型初始化。我實際上必須在幾乎所有的活動中都做這個檢查。

+0

這絕對是一個非常糟糕和不可靠的設計。活動不應該初始化全局變量。然後,它不應該將它們存儲在應用程序中。當然,它不應該做任何「初始化」工作來啓動另一個活動,而是作爲服務工作。如果要存儲數據,則有SharedPreferences類。如果你想做一些繁重的工作,你可以使用Sevice,AsyncTask或保留實例Fragment。但不要做你所描述的。簡單的配置更改可能會破壞整個應用程序。 – Drew

+0

不知道你爲什麼如此重要,也許我不是很清楚。 ActivityA是一個啓動/標誌屏幕。它啓動AsyncTask來初始化各種緩存,然後啓動ActivityB。對這些緩存的引用存儲在Application對象中。當Application對象被銷燬時,緩存必須重新初始化,最簡單的方法是返回到ActivityA。我不明白你在說什麼配置改變,當這些改變發生時,ActivityB只是通過OS的onCreate()重新啓動,並且由於Application對象沒有被銷燬,一切都很好。 –

+0

沒有代碼很難說,但通過這樣做你可以很好地「泄漏活動」 - 創建一個常見的Android內存泄漏。 **配置更改**是例如更改屏幕方向。它會導致Activity再次破壞並創建生命週期。通過發佈AsyncTask而不處理配置更改,您可能會遇到:內存泄漏(泄漏整個Activity);併發問題(兩個AsyncTasks - 屬於不活動Activity和新創建的一個 - 競爭將數據傳遞給Application);至少NullPointerException;等 – Drew

相關問題