2011年12月28日 星期三

Android - Runtime Changes (1) - Retaining an Object (getLastNonConfigurationInstance, onRetainNonConfigurationInstance)

當你旋轉手機由直立改為橫立時,畫面上的Activity的life cycle會進行下列動作
onPause
onStop
onDestroy
onCreate
onStart
onResume

換 言之Activity會被消滅然後再重新產生一次,這時候有一個問題就是原本畫面上資料會消失,或者是在onCreate的動作會重新再做一次。這種問題 應該被避免。假設onCreate會sendBroadcast去啟動某件事情,則你不停的旋轉手機就會不停的發送sendBroadcast。或者你原 本讓使用者在畫面上輸入一些資料,然後進行一些運算,如果使用者不小心旋轉畫面後,運算結果都消失了。這些情況應該都要被避免,官方說法很清楚,這邊簡單示範程式:

(1) 利用一個Class來記錄資料
(2) @Override
      public Object onRetainNonConfigurationInstance()
(3) 在onCreate()裡面利用getLastNonConfigurationInstance()把舊資料取出來

public class Main extends Activity {
   
    private class MyDataClass{
        int mIntValue;
        boolean mBoolValue;
        String mStringValue;
    }
   
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.d("Test","onCreate()");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        MyDataClass data = (MyDataClass) getLastNonConfigurationInstance();
        if (data == null) {
            data = loadMyData();
        }  
       
        Log.d("Test","The mIntValue = " + data.mIntValue);
        Log.d("Test","The mBoolValue = " + data.mBoolValue);
        Log.d("Test","The mStringValue = " + data.mStringValue);
       
    }
   
    @Override
    public Object onRetainNonConfigurationInstance() {
        Log.d("Test","onRetainNonConfigurationInstance()");
        final MyDataClass data = collectMyLoadedData();
        return data;
    }
   
    private MyDataClass collectMyLoadedData(){
        Log.d("Test","collectMyLoadedData()");
        MyDataClass returnData = new MyDataClass();
        returnData.mIntValue = 10;
        returnData.mBoolValue = true;
        returnData.mStringValue = "loaded data";
       
        return returnData;
    }
   
    private MyDataClass loadMyData(){
        Log.d("Test","loadMyData()");
        MyDataClass returnData = new MyDataClass();
        returnData.mIntValue = 0;
        returnData.mBoolValue = false;
        returnData.mStringValue = "default data";
       
        return returnData;      
    } 
}

先執行程式,Log如下
DEBUG/Test(11361): onCreate()
DEBUG/Test(11361): loadMyData()
DEBUG/Test(11361): The mIntValue = 0
DEBUG/Test(11361): The mBoolValue = false
DEBUG/Test(11361): The mStringValue = default data

然後再旋轉手機後,Log如下
DEBUG/Test(11361): onRetainNonConfigurationInstance()
DEBUG/Test(11361): collectMyLoadedData()
DEBUG/Test(11361): onCreate()
DEBUG/Test(11361): The mIntValue = 10
DEBUG/Test(11361): The mBoolValue = true
DEBUG/Test(11361): The mStringValue = loaded data

可以看到旋轉完手機後,資料和第一次執行的值不同。

沒有留言:

張貼留言