日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复

發(fā)布時間:2025/4/16 Android 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Android中的狀態(tài)保存和恢復(fù)

Android中的狀態(tài)保存和恢復(fù), 包括Activity和Fragment以及其中View的狀態(tài)處理.
Activity的狀態(tài)除了其中的View和Fragment的狀態(tài)之外, 還需要用戶手動保存一些成員變量.
Fragment的狀態(tài)有它自己的實例狀態(tài)和其中的View狀態(tài), 因為其生命周期的靈活性和實際需要的不同, 情況會多一些.
根據(jù)源碼, 列出了Fragment中實例狀態(tài)和View狀態(tài)保存和恢復(fù)的幾個入口, 便于分析查看.
最后專門講了WebView狀態(tài)保存和恢復(fù), 問題及處理.
還有一個工具類icepick的介紹.

Activity的狀態(tài)保存和恢復(fù)

作為熱身, 先來講一下Activity的狀態(tài)保存和恢復(fù).

什么時候需要恢復(fù)Activity

關(guān)于Activity的銷毀和重建, 之前有這么一篇博文: Activity的重新創(chuàng)建
總結(jié)來說, 就是Activity的銷毀, 分為徹底銷毀和留下數(shù)據(jù)的銷毀兩種.

徹底銷毀是指用戶主動去關(guān)閉或退出這個Activity. 此時是不需要狀態(tài)恢復(fù)的, 因為下次回來又是重新創(chuàng)建全新的實例.
留下數(shù)據(jù)的銷毀是指系統(tǒng)銷毀了activity, 但是當(dāng)用戶返回來時, 會重新創(chuàng)建它, 讓用戶覺得它一直都在.

屏幕旋轉(zhuǎn)重建可以歸結(jié)為第二種情況, 打開Do not keep activities開關(guān), 切換activities也是會出現(xiàn)第二種情況.
打開Do not keep activities開關(guān)就是為了模擬內(nèi)存不足時的系統(tǒng)行為, 這里有一篇分析

如何恢復(fù)

實際上系統(tǒng)已經(jīng)幫我們做好了View層面基本的恢復(fù)工作, 主要是依靠下面兩個方法:

@Overrideprotected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // 在onStop()之前調(diào)用, 文檔中說并不保證在onPause()的之前還是之后 // 我的試驗中一般是在onPause()之后 } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); // 在onStart() 之后 }

Bundle其中包含了activity中的view和fragment的各種信息, 所以調(diào)用基類的方法就可以完成基本的view層面的恢復(fù)工作.
注意這兩個方法并不是activity的生命周期回調(diào), 對于activity來說它們不是一定會發(fā)生的.
另外需要注意的是, View必須要有id才能被恢復(fù).

舉一個實例來說明:
Activity A start B, 那么A的onSaveInstanceState()會在onStop()之前調(diào)用, 以防A被系統(tǒng)銷毀.
但是在B中按下back鍵finish()了自己后, B被銷毀的過程中, 并沒有調(diào)用onSaveInstanceState(), 是因為B并沒有被壓入task的back stack中,
也即系統(tǒng)知道B并不需要儲存自己的狀態(tài).
正常情況下, 返回到A, A沒有被銷毀, 也不會調(diào)用onRestoreInstanceState(), 因為所有的狀態(tài)都還在, 并不需要重建.

如果我們打開了Do not keep activities開關(guān), 模擬系統(tǒng)內(nèi)存不足時的行為, 從A到B, 可以看到當(dāng)B resume的時候A會一路走到onDestroy(),
而關(guān)掉B之后, A會從onCreate()開始走, 此時onCreate()的參數(shù)bundle就不為空了, onStart()之后會調(diào)用onRestoreInstanceState()方法, 其參數(shù)bundle中內(nèi)容類似于如下:

Bundle[{android:viewHierarchyState=Bundle[mParcelledData.dataSize=272]}]

其中包含了View的狀態(tài), 如果有Fragment, 也會包含F(xiàn)ragment的狀態(tài), 其實質(zhì)是保存了FragmentManagerState, 內(nèi)容類似于如下:

Bundle[{android:viewHierarchyState=Bundle[{android:views={16908290=android.view.AbsSavedState$1@bc382e7, 2131492950=CompoundButton.SavedState{4034f96 checked=true}, 2131492951=android.view.AbsSavedState$1@bc382e7}}], android:fragments=android.app.FragmentManagerState@bacc717}]

對于上面的例子來說, B什么時候會調(diào)用onSaveInstanceState()呢?
當(dāng)從A打開B之后, 按下Home鍵, B就會調(diào)用onSaveInstanceState().
因為這時候系統(tǒng)不知道用戶什么時候會返回, 有可能會把B也銷毀了, 所以保存一下它的狀態(tài).
如果下次回來它沒有被重建, onRestoreInstanceState()就不會被調(diào)用, 如果它被重建了, onRestoreInstanceState()才會被調(diào)用.

Activity保存方法的調(diào)用時機

activity的onSaveInstanceState()和onRestoreInstanceState()方法在如下情形下會調(diào)用:

  • 屏幕旋轉(zhuǎn)重建: 先save再restore.
  • 啟動另一個activity: 當(dāng)前activity在離開前會save, 返回時如果因為被系統(tǒng)殺死需要重建, 則會從onCreate()重新開始生命周期, 調(diào)用onRestoreInstanceState(); 如果沒有重建, 則不會調(diào)用onCreate(), 也不會調(diào)用onRestoreInstanceState(), 生命周期從onRestart()開始, 接著onStart()和onResume().
  • 按Home鍵的情形和啟動另一個activity一樣, 當(dāng)前activity在離開前會save, 用戶再次點擊應(yīng)用圖標(biāo)返回時, 如果重建發(fā)生, 則會調(diào)用onCreate()和onRestoreInstanceState(); 如果activity不需要重建, 只是onRestart(), 則不會調(diào)用onRestoreInstanceState().
  • Activity恢復(fù)方法的調(diào)用時機

    activity的onSaveInstanceState()和onRestoreInstanceState()方法在如下情形下不會調(diào)用:

  • 用戶主動finish()掉的activity不會調(diào)用onSaveInstanceState(), 包括主動按back退出的情況.
  • 新建的activity, 從onCreate()開始, 不會調(diào)用onRestoreInstanceState().
  • Activity中還需要手動恢復(fù)什么

    如上, 系統(tǒng)已經(jīng)為我們恢復(fù)了activity中的各種view和fragment, 那么我們自己需要保存和恢復(fù)一些什么呢?
    答案是成員變量值.

    因為系統(tǒng)并不知道你的各種成員變量有什么用, 哪些值需要保存, 所以需要你自己覆寫上面兩個方法, 然后把自己需要保存的值加進bundle里面去. 具體例子, 這里Activity的重新創(chuàng)建有, 我就不重復(fù)了.
    重要的是不要忘記調(diào)用super的方法, 那里有系統(tǒng)幫我們恢復(fù)的工作.

    工具類Icepick介紹

    在介紹下面的內(nèi)容之前, 先介紹一個小工具: Icepick
    這個工具的作用是, 在你想保存和重建自己的成員變量數(shù)據(jù)時, 幫你省去那些put和get方法的調(diào)用, 你也不用為每一個字段起一個常量key.
    你需要做的就是簡單地在你想要保存狀態(tài)的字段上面加上一個@State 注解.
    然后在保存和恢復(fù)的時候分別加上一句話:

    @Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Icepick.restoreInstanceState(this, savedInstanceState); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Icepick.saveInstanceState(this, outState); }

    然后你的成員變量就有了它應(yīng)該有的值了, DONE!

    Fragment的狀態(tài)保存和恢復(fù)

    Fragment的狀態(tài)比Activity的要復(fù)雜一些, 因為它的生命周期狀態(tài)比較多.

    Fragment狀態(tài)保存和恢復(fù)的相關(guān)方法

    按照上面的思路, 我先去查找Fragment中保存和恢復(fù)的回調(diào)方法了.
    Fragment的狀態(tài)保存回調(diào)是這個方法:

    public void onSaveInstanceState(Bundle outState) { // may be called any time before onDestroy() }

    這個方法和之前activity的情況大體是類似的, 它不是生命周期的回調(diào), 所以只在有需要的時候會調(diào)到.
    onSaveInstanceState()在activity調(diào)用onSaveInstanceState()的時候發(fā)生, 用于保存實例狀態(tài).(看它的方法名: instance state).
    onSaveInstanceState()方法保存的bundle會返回給幾個生命周期回調(diào): onCreate(), onCreateView(), onViewCreated()和onActivityCreated().

    Fragment并沒有對應(yīng)的onRestoreInstanceState()方法.
    也即沒有實例狀態(tài)的恢復(fù)回調(diào).

    Fragment只有一個onViewStateRestored()的回調(diào)方法:

    public void onViewStateRestored(@Nullable Bundle savedInstanceState) { // 在onActivityCreated()和onStart()之間調(diào)用 mCalled = true; }

    onViewStateRestored()每次新建Fragment都會發(fā)生.
    它并不是實例狀態(tài)恢復(fù)的方法, 只是一個View狀態(tài)恢復(fù)的回調(diào).

    這里需要注意, Fragment的狀態(tài)分兩個類型: 實例狀態(tài)和View狀態(tài).
    這里有個最佳實踐: The Real Best Practices to Save/Restore Activity's and Fragment's state
    不要把Fragment的實例狀態(tài)和View狀態(tài)混在一起處理.

    在這里我先上個結(jié)論, 把查看源碼中Fragment狀態(tài)保存和恢復(fù)的相關(guān)方法列出來:

    Fragment狀態(tài)保存入口:

    Fragment的狀態(tài)保存入口有三個:

  • Activity的狀態(tài)保存, 在Activity的onSaveInstanceState()里, 調(diào)用了FragmentManger的saveAllState()方法, 其中會對mActive中各個Fragment的實例狀態(tài)和View狀態(tài)分別進行保存.
  • FragmentManager還提供了public方法: saveFragmentInstanceState(), 可以對單個Fragment進行狀態(tài)保存, 這是提供給我們用的, 后面會有例子介紹這個. 其中調(diào)用的saveFragmentBasicState()方法即為情況一中所用, 圖中已畫出標(biāo)記.
  • FragmentManager的moveToState()方法中, 當(dāng)狀態(tài)回退到ACTIVITY_CREATED, 會調(diào)用saveFragmentViewState()方法, 保存View的狀態(tài).
  • moveToState()方法中有很長的switch case, 中間不帶break, 基本是根據(jù)新狀態(tài)和當(dāng)前狀態(tài)的比較, 分為正向創(chuàng)建和反向銷毀兩個方向, 一路沿著多個case走下去.

    Fragment狀態(tài)恢復(fù)入口:

    三個恢復(fù)的入口和三個保存的入口剛好對應(yīng).

  • 在Activity重新創(chuàng)建的時候, 恢復(fù)所有的Fragment狀態(tài).
  • 如果調(diào)用了FragmentManager的方法: saveFragmentInstanceState(), 返回值得到的狀態(tài)可以用Fragment的setInitialSavedState()方法設(shè)置給新的Fragment實例, 作為初始狀態(tài).
  • FragmentManager的moveToState()方法中, 當(dāng)狀態(tài)正向創(chuàng)建到CREATED時, Fragment自己會恢復(fù)View的狀態(tài).
  • 這三個入口分別對應(yīng)的情況是:
    入口1對應(yīng)系統(tǒng)銷毀和重建新實例.
    入口2對應(yīng)用戶自定義銷毀和創(chuàng)建新Fragment實例的狀態(tài)傳遞.
    入口3對應(yīng)同一Fragment實例自身的View狀態(tài)重建.

    Fragment狀態(tài)保存恢復(fù)和Activity的聯(lián)系

    這里對應(yīng)的是入口1的情況.
    當(dāng)Activity在做狀態(tài)保存和恢復(fù)的時候, 在它其中的fragment自然也需要做狀態(tài)保存和恢復(fù).
    所以Fragment的onSaveInstanceState()在activity調(diào)用onSaveInstanceState()的時候一定會發(fā)生.
    同樣的, 如果Fragment中有一些成員變量的值在此時需要保存, 也可以用@State標(biāo)記, 處理方法和上面一樣.
    也即, 在Activity需要保存狀態(tài)的時候, 其中的Fragments的實例狀態(tài)自動被處理保存.

    Fragment同一實例的View狀態(tài)恢復(fù)

    這里對應(yīng)的是入口3的情況.
    前面介紹過, activity在保存狀態(tài)的時候, 會將所有View和Fragment的狀態(tài)都保存起來等待重建的時候使用.
    但是如果是單個Activity對應(yīng)多個Fragments的架構(gòu), Activity永遠是resume狀態(tài), 多個Fragments在切換的過程中, 沒有activity的幫助, 如何保存自己的狀態(tài)?

    首先, 取決于你的多個Fragments是如何初始化的.
    我做了一個實驗, 在activity的onCreate()里面初始化兩個Fragment:

    private void initFragments() { tab1Fragment = getFragmentManager().findFragmentByTag(Tab1Fragment.TAG); if (tab1Fragment == null) { tab1Fragment = new Tab1Fragment(); } tab2Fragment = getFragmentManager().findFragmentByTag(Tab2Fragment.TAG); if (tab2Fragment == null) { tab2Fragment = new Tab2Fragment(); } }

    然后點擊兩個按鈕來切換它們, replace(), 并且不加入到back stack中:

    @OnClick(R.id.tab1) void onTab1Clicked() { getFragmentManager().beginTransaction() .replace(R.id.content_container, tab1Fragment, Tab1Fragment.TAG) .commit(); } @OnClick(R.id.tab2) void onTab2Clicked() { getFragmentManager().beginTransaction() .replace(R.id.content_container, tab2Fragment, Tab2Fragment.TAG) .commit(); }

    可以看到, 每一次的切換, 都是一個Fragment的完全destroy, detach和另一個fragment的attach, create,
    但是當(dāng)我在這兩個fragment中各自加上EditText, 發(fā)現(xiàn)只要EditText有id, 切換過程中EditText的內(nèi)容是被保存的.
    這是誰在什么時候保存并恢復(fù)的呢?
    我在TextChange的回調(diào)里打了斷點, 發(fā)現(xiàn)調(diào)用棧如下:

    在FragmentManagerImpl中, moveToState()方法的case Fragment.CREATED中:
    調(diào)用了: f.restoreViewState(f.mSavedFragmentState);
    此時我沒有做任何保存狀態(tài)的處理, 但是斷點中可以看出:

    雖然mSavedFragmentState是null, 但是mSavedViewState卻有值.
    所以這個View狀態(tài)保存和恢復(fù)對應(yīng)的入口即是上面兩個圖中的入口三.

    這是因為我的兩個fragment只new了一次, 然后保存了成員變量, 即便是Fragment重新onCreate(), 但是對應(yīng)的實例仍然是同一個.
    這和Activity是不同的, 因為你是無法new一個Activity的.

    在上面的例子中, 如果不保存Fragment的引用, 每次都new Fragment, 那么View的狀態(tài)是不會被保存的, 因為不同實例間的狀態(tài)傳遞只有在系統(tǒng)銷毀恢復(fù)的情況下才會發(fā)生(入口一).
    如果我們需要在不同的實例間傳遞狀態(tài), 就需要用到下面的方法.

    不同F(xiàn)ragment實例間的狀態(tài)保存和恢復(fù)

    這里對應(yīng)的是入口2, 不同于入口1和3, 它們是自動的, 入口2是用戶主動保存和恢復(fù)的情形.
    自己主動保存Fragment的狀態(tài), 可以調(diào)用FragmentManager的這個方法:

    public abstract Fragment.SavedState saveFragmentInstanceState(Fragment f);

    它的實現(xiàn)是這樣的:

    @Override public Fragment.SavedState saveFragmentInstanceState(Fragment fragment) { if (fragment.mIndex < 0) { throwException(new IllegalStateException("Fragment " + fragment + " is not currently in the FragmentManager")); } if (fragment.mState > Fragment.INITIALIZING) { Bundle result = saveFragmentBasicState(fragment); return result != null ? new Fragment.SavedState(result) : null; } return null; }

    返回的數(shù)據(jù)類型是: Fragment.SavedState, 這個state可以通過Fragment的這個方法設(shè)置給自己:

    public void setInitialSavedState(SavedState state) { if (mIndex >= 0) { throw new IllegalStateException("Fragment already active"); } mSavedFragmentState = state != null && state.mState != null ? state.mState : null; }

    但是注意只能在Fragment被加入之前設(shè)置, 這是一個初始狀態(tài).
    利用這兩個方法可以更加自由地保存和恢復(fù)狀態(tài), 而不依賴于Activity.
    這樣處理以后, 不必保存Fragment的引用, 每次切換的時候雖然都new了新的實例, 但是舊的實例的狀態(tài)可以設(shè)置給新實例.

    例子代碼:

    @State SparseArray<Fragment.SavedState> savedStateSparseArray = new SparseArray<>(); void onTab1Clicked() { // save current tab Fragment tab2Fragment = getSupportFragmentManager().findFragmentByTag(Tab2Fragment.TAG); if (tab2Fragment != null) { saveFragmentState(1, tab2Fragment); } // restore last state Tab1Fragment tab1Fragment = new Tab1Fragment(); restoreFragmentState(0, tab1Fragment); // show new tab getSupportFragmentManager().beginTransaction() .replace(R.id.content_container, tab1Fragment, Tab1Fragment.TAG) .commit(); } private void saveFragmentState(int index, Fragment fragment) { Fragment.SavedState savedState = getSupportFragmentManager().saveFragmentInstanceState(fragment); savedStateSparseArray.put(index, savedState); } private void restoreFragmentState(int index, Fragment fragment) { Fragment.SavedState savedState = savedStateSparseArray.get(index); fragment.setInitialSavedState(savedState); }

    注意這里用了SparseArray來存儲Fragment的狀態(tài), 并且加上了@State, 這樣在Activity重建的時候其中的內(nèi)容也能夠被恢復(fù).

    Back stack中的fragment

    有一點很特殊的是, 當(dāng)Fragment從back stack中返回, 實際上是經(jīng)歷了一次View的銷毀和重建, 但是它本身并沒有被重建.
    即View狀態(tài)需要重建, 實例狀態(tài)不需要重建.

    舉個例子說明這種情形: Fragment被另一個Fragment replace(), 并且壓入back stack中, 此時它的View是被銷毀的, 但是它本身并沒有被銷毀.
    也即, 它走到了onDestroyView(), 卻沒有走onDestroy()和onDetact().
    等back回來的時候, 它的view會被重建, 重新從onCreateView()開始走生命周期.
    在這整個過程中, 該Fragment中的成員變量是保持不變的, 只有View會被重新創(chuàng)建.
    在這個過程中, instance state的saving并沒有發(fā)生.

    所以, 很多時候Fragment還需要考慮的是在沒有Activity幫助的情形下(Activity并沒有可能重建的情形), 自身View狀態(tài)的保存.
    此時要注意一些不容易發(fā)現(xiàn)的錯誤, 比如List的新實例需要重新setAdapter等.

    Fragment setRetainInstance

    Fragment有一個相關(guān)方法:
    setRetainInstance
    這個方法設(shè)置為true的時候表示, 即便activity重建了, 但是fragment的實例并不被重建.
    注意此方法只對沒有放在back stack中的fragment生效.
    什么時候要用這個方法呢? 處理configuration change的時候:
    Handling Configuration Changes with Fragments
    這樣, 當(dāng)屏幕旋轉(zhuǎn), Activity重建, 但是其中的fragment和fragment正在執(zhí)行的任務(wù)不必重建.
    更多解釋可以參見:
    http://stackoverflow.com/questions/11182180/understanding-fragments-setretaininstanceboolean
    http://stackoverflow.com/questions/11160412/why-use-fragmentsetretaininstanceboolean

    注意這個方法只是針對configuration change, 并不影響用戶主動關(guān)閉和系統(tǒng)銷毀的情況:
    當(dāng)activity被用戶主動finish, 其中的所有fragments仍然會被銷毀.
    當(dāng)activity不在最頂端, memory不夠了, 系統(tǒng)仍然可能會銷毀activity和其中的fragments.

    View的狀態(tài)保存和恢復(fù)

    View的狀態(tài)保存和恢復(fù)主要是依賴于下面幾個方法:
    保存: saveHierarchyState() -> dispatchSaveInstanceState() -> onSaveInstanceState()
    恢復(fù): restoreHierarchyState() -> dispatchRestoreInstanceState() -> onRestoreInstanceState()
    還有兩個重要的前提條件是View要有id, 并且setSavedEnabled()為true.(這個值默認(rèn)為true).
    在系統(tǒng)的widget里(比如TextView, EditText, Checkbox等), 這些都是已經(jīng)被處理好的, 我們只需要給View賦予id, Activity和Fragment重建的時候會自動恢復(fù)其中的狀態(tài). (這里的Fragment恢復(fù)對應(yīng)入口一和入口三, 入口二屬于跨實例新建的情況).

    但是如果你要使用第三方的自定義View, 就需要確認(rèn)一下它們內(nèi)部是否有狀態(tài)保存和恢復(fù)的代碼.
    如果不行你就需要繼承該自定義View, 然后實現(xiàn)這兩個方法:

    // // Assumes that SomeSmartButton is a 3rd Party view that // View State Saving/Restoring are not implemented internally // public class SomeBetterSmartButton extends SomeSmartButton { ... @Override public Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); // Save current View's state here return bundle; } @Override public void onRestoreInstanceState(Parcelable state) { super.onRestoreInstanceState(state); // Restore View's state here } ... }

    WebView的狀態(tài)保存和恢復(fù)

    WebView的狀態(tài)保存和恢復(fù)不像其他原生View一樣是自動完成的.
    WebView不是繼承自View的.
    如果我們把WebView放在布局里, 不加處理, 那么Activity或Fragment重建的過程中, WebView的狀態(tài)就會丟失, 變成初始狀態(tài).

    在Fragment的onSaveInstanceState()里面可以加入如下代碼來保存WebView的狀態(tài):

    @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); webView.saveState(outState); }

    然后在初始化的時候, 增加判斷, 不必每次都打開初始鏈接:

    if (savedInstanceState != null) {webView.restoreState(savedInstanceState); } else {webView.loadUrl(TEST_URL); }

    這樣處理以后, 在重新建立的時候, WebView的狀態(tài)就能恢復(fù)到離開前的頁面.
    不論WebView是放在Activity里還是Fragment里, 這個方法都適用.

    但是Fragment還有另一種情況, 即Fragment被壓入back stack, 此時它沒有被destroy(), 所以沒有調(diào)用onSavedInstanceState()這個方法.
    這種情況返回的時候, 會從onCreateView()開始, 并且savedInstanceState為null, 于是其中WebView之前的狀態(tài)在此時丟失了.
    解決這種情況可以利用Fragment實例并未銷毀的條件, 增加一個成員變量bundle, 保存WebView的狀態(tài), 最終解決如下:

    private Bundle webViewState;@Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ButterKnife.bind(this, view); initWebView(); if (webViewState != null) { //Fragment實例并未被銷毀, 重新create view webView.restoreState(webViewState); } else if (savedInstanceState != null) { //Fragment實例被銷毀重建 webView.restoreState(savedInstanceState); } else { //全新Fragment webView.loadUrl(TEST_URL); } } @Override public void onPause() { super.onPause(); webView.onPause(); //Fragment不被銷毀(Fragment被加入back stack)的情況下, 依靠Fragment中的成員變量保存WebView狀態(tài) webViewState = new Bundle(); webView.saveState(webViewState); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); //Fragment被銷毀的情況, 依靠outState保存WebView狀態(tài) if (webView != null) { webView.saveState(outState); } }

    本文完整例子相關(guān)實驗代碼可見:
    HelloActivityAndFragment
    中的State Restore Demo.

    本文地址: Android Fragment使用(三) Activity, Fragment, WebView的狀態(tài)保存和恢復(fù)

    參考資料

    Developer Android:
    Android Fragment Reference
    Android FragmentManager Reference

    Posts:
    Recreating an Activity
    Activity的重新創(chuàng)建
    從源碼角度剖析Fragment核心知識點
    Fragment源碼閱讀筆記
    The Real Best Practices to Save/Restore Activity's and Fragment's state
    Android中保存和恢復(fù)Fragment狀態(tài)的最好方法

    Handling Configuration Changes with Fragments
    Saving Android View state correctly

    總結(jié)

    以上是生活随笔為你收集整理的Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 宅男午夜影院 | 国产日韩久久久 | www.日韩av.com | 女人喂男人奶水做爰视频 | 中文天堂在线资源 | 在线看中文字幕 | 性の欲びの女javhd | 高h亲子乱h | 欧洲成人一区二区三区 | 久久国产一区 | a少妇| 日本三不卡 | 你懂的在线网站 | 已婚少妇美妙人妻系列 | 99午夜| 奇米影视久久 | 日韩一区二区三区网站 | 国产凹凸一区二二区 | 污污网站在线看 | 爱色av网站 | 欧美精品乱人伦久久久久久 | 国产伦精品一区二区三区精品 | 国产欧美一区二区三区在线 | 爱草视频 | 香蕉久久综合 | 国产99久久九九精品无码免费 | 国产福利一区在线观看 | 内射干少妇亚洲69xxx | 精品视频导航 | 亚洲免费观看高清完整版在线 | 丰满人妻综合一区二区三区 | 在线看片一区二区 | 丰满雪白极品少妇流白浆 | 97精品一区二区 | 日韩久久久久久久 | 国产一区在线观看免费 | 天啪 | 国产亚韩| 呦呦精品 | 欧美人和黑人牲交网站上线 | 精品一区二区三区精华液 | 精品免费一区 | aaa成人 | 国产精品电影一区 | 二区三区在线观看 | 超碰男人天堂 | 成人国产精品免费观看 | 美女被啪羞羞粉色视频 | 亚洲午夜精品久久久久久人妖 | 一区二区三区精品国产 | 天天射寡妇 | 麻豆极品 | 久久久久国产综合av天堂 | 国产婷婷色 | 欧美成人精品一区二区三区在线看 | 国语对白做受按摩的注意事项 | 欧美性生活网站 | 日韩一区二区三区久久 | 男女午夜激情 | 96视频在线 | 亚洲一级一级 | 久久久久亚洲av无码专区桃色 | 九九影视理伦片 | 无码久久av一区二区三区 | 一级不卡毛片 | 日韩久久久久久久久久久 | 99色这里只有精品 | 秘密基地动漫在线观看免费 | 久久久久久久久久国产精品 | 国产人妖ts | 国产福利精品一区 | 1024手机在线观看 | 亚洲精品区| 中文字幕在线免费看 | 日本三级小视频 | 日本加勒比在线 | 亚洲欧美日韩国产 | 无人在线观看高清视频 | 日本三区视频 | 男女免费视频网站 | 男女免费观看视频 | 国产一区不卡 | 亚洲国产成人一区二区 | jizzjizz亚洲| 一二三区精品视频 | 谁有毛片网站 | 一区二区三区四区影院 | 午夜影院日本 | 天天色综合图片 | 视频福利一区 | 亚洲不卡影院 | 国产精品无码网站 | 国产做受麻豆动漫 | 五月依人网| 精品视频一二区 | 中文字幕免费av | 男同av在线观看一区二区三区 | 日韩视频一区二区三区在线播放免费观看 | 亚洲成年人在线观看 |