2011年8月4日 星期四

連續變換方向導致記憶體不足

發現自己開發的Android軟體,有一個問題。如果頻煩地更換方向,一下直,一下橫,多幾次,系統就出現異常錯誤。
因此,就追蹤了一下,直/橫的變化,系統作了些什麼? 結果發現,方向變化時,系統會執行onCreate(), 自己在onCreate中,讀數據庫,讀出列表,顯示在螢幕上,列表中,每一列又有圖標,這麼一下,來來回回,不斷重做,讀出的記憶體,沒有及時釋放,(自己一直不想去控制GC, Garbage Collection, 自己的程式還不是那麼大,殺雞焉用牛刀),結果系統就當掉了,因此,就想,那讀出來的資料就不要再讀了,做過的事,就不要再做了,因此,
  1. 第一個想到,就將變數移成class member, 在讀出來前,先判斷一下,是否為null, 若是null再重讀。
  2. 乖乖,結果相同,想當然耳,會執行onCreate(), 自然是重新產生一個instance,所有的data member當然被reset了,那怎麼辦?
  3. 那就用static,將這個變數鎖住,測試,對了正常了,怎麼變換都不會當了,只有第一次做,以後就不做了。可是有一個問題要處理。每一次啟動這個Activity, 變數將會保留上一個,也不會重新讀取(如果每次需要讀不同的資料)。
  4. 那把清空的動作加在onStop()好了,在結束時設為null, 下回進來就會重讀。測試,結果方向變化也會執行onStop()…..怎麼辦?
  5. 那試onDestroy()好了,方向變換應該不會進行”破壞”吧!很不幸地,方向變換時,依然執行了onDestroy(), 那怎麼辦?
  6. 這麼基本的需求,一定有解。結果發現,在onDestroy()中加上isFinishing()的判斷就好了,如果是方向變換,isFinishing()會傳回false, 如果是結束,就會傳回true。(在onStop()中做,應該也是可以的,想Stop()未必結束,只要沒有Destroy應該都不必重讀,放在onDestroy()中比較省功。

@Override
protected void onDestroy() {
/*
* When you change orientation, onDestroy will be invoked too.
*/
super.onDestroy();
if(this.isFinishing()) {
files=null;
index=0;
bm=null;
}
}

沒有留言:

張貼留言