1. 程式人生 > >activity/fragment view的儲存恢復

activity/fragment view的儲存恢復

儲存/恢復 activity和fragment

一、activity

當Activity的onSaveInstanceState被呼叫的時候,Activity將會從View 層次(View Hierachy)中的每一個View中自動蒐集View的狀態。請注意,只會蒐集實現了View狀態儲存/恢復的內部方法的View的資料。一旦onRestoreInstanceState被呼叫,Activity將會將這些蒐集到的資料一對一的返還給View 層次裡在蒐集的時候提供了同樣的android:id屬性的View。

這就是為什麼儘管Activity已經被銷燬,而我們並沒有做一些特別的事情來儲存狀態,但是EditText中鍵入的文字仍然能夠呈現的原因。這並不是什麼魔法,這些View 的狀態已經被自動的儲存和恢復回來了。

這也是為什麼View 在沒有被設定android:id屬性的時候不能儲存和恢復自己的狀態的原因。

儘管這些View 的狀態被自動的儲存了,但是Activity的成員變數並不會有同樣的效果。這些成員變數會被和Activity一起銷燬。你可以手動的儲存和恢復它們,通過onSaveInstanceStateonRestoreInstanceState方法。

public class MainActivity extends AppCompatActivity {

    // These variable are destroyed along with Activity
    private int someVarA;
    private String someVarB;

    ...

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("someVarA", someVarA);
        outState.putString("someVarB", someVarB);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        someVarA = savedInstanceState.getInt("someVarA");
        someVarB = savedInstanceState.getString("someVarB");
    }

}

 

二、fragment

一旦Fragment從後退棧中返回,它的View 會被銷燬,並重新建立。

這種情況下,Fragment並不會被銷燬,只有Fragment中的View 會被銷燬。 結果是,並不會發生任何例項狀態的儲存。但是上面展示的這些View在Fragment生命週期中被重新建立時,發生了什麼?

別驚訝,因為Android是這樣設計的。在這種情況下,Fragment中的View 狀態的儲存/恢復會被內部呼叫。結果就是,每一個實現了內部View 狀態儲存/恢復的View ,將會被自動的儲存並且恢復狀態,例如帶有android:freezeText="true"

屬性的EditText或者TextView。就之前完美顯示的一樣。

請注意,在這種情況下,只有View 被銷燬(並重建)了。Fragment仍然在這裡,就像它內部的成員變數一樣。所以你不需要對它們做任何事情。不需要任何額外的程式碼。

 

public class MainFragment extends Fragment {

    // These variable are destroyed along with Activity
    private int someVarA;
    private String someVarB;

    ...

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("someVarA", someVarA);
        outState.putString("someVarB", someVarB);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        someVarA = savedInstanceState.getInt("someVarA");
        someVarB = savedInstanceState.getString("someVarB");
    }

}

如果Fragment中的每一個View 都在內部實現了View 的狀態的儲存和恢復.在這種情況下,你就沒有必要做任何事情,View 狀態會被自動的恢復,並且Fragment中的成員變數也和之前的一樣。

所以Fragment狀態儲存/恢復最佳實踐的第一條件就是...

你應用中使用的每一個單獨的View都必須在內部實現狀態的儲存和恢復

Android內部通過onSaveInstanceStateonRestoreInstanceState 方法提供了儲存和恢復View 狀態的機制。開發者的任務就是實現它。

基本上來說,每一個單獨的Android提供的的標準View 元件都已經在內部完成了這些事情,例如EditText,TextView,Checkbox.
儘管也許你手動讓它生效,例如,你需要為TextView設定android:freezeText為true,來使用這個功能。

但是如果我們討論關於網際網路上貢獻的第三方的自定義元件。我必須說,它們大多數都沒有實現這部分的程式碼,在使用中會導致很大的問題。

如果你決定使用第三方的自定義元件,你不得不確保它已經在內部實現了View 的儲存和恢復,否則你必須建立繼承這個三方元件的一個派生的子類,並且自己實現onSaveInstanceStateonRestoreInstanceState方法。

並且不要忘記為每一個你需要開啟View狀態儲存和恢復的View設定android:id屬性,不然它們的狀態不能正確的恢復。