1. 程式人生 > >Activity, Fragment, WebView的狀態儲存和恢復

Activity, Fragment, WebView的狀態儲存和恢復

Android中的狀態儲存和恢復

Android中的狀態儲存和恢復, 包括Activity和Fragment以及其中View的狀態處理.
Activity的狀態除了其中的View和Fragment的狀態之外, 還需要使用者手動儲存一些成員變數.
Fragment的狀態有它自己的例項狀態和其中的View狀態, 因為其生命週期的靈活性和實際需要的不同, 情況會多一些.
根據原始碼, 列出了Fragment中例項狀態和View狀態儲存和恢復的幾個入口, 便於分析檢視.
最後專門講了WebView狀態儲存和恢復, 問題及處理.
還有一個工具類icepick的介紹.

Activity的狀態儲存和恢復

作為熱身, 先來講一下Activity的狀態儲存和恢復.

什麼時候需要恢復Activity

關於Activity的銷燬和重建, 之前有這麼一篇博文: Activity的重新建立
總結來說, 就是Activity的銷燬, 分為徹底銷燬和留下資料的銷燬兩種.

徹底銷燬是指使用者主動去關閉或退出這個Activity. 此時是不需要狀態恢復的, 因為下次回來又是重新建立全新的例項.
留下資料的銷燬是指系統銷燬了activity, 但是當用戶返回來時, 會重新建立它, 讓使用者覺得它一直都在.

螢幕旋轉重建可以歸結為第二種情況, 開啟Do not keep activities開關, 切換activities也是會出現第二種情況.
開啟Do not keep activities

開關就是為了模擬記憶體不足時的系統行為, 這裡有一篇分析

如何恢復

實際上系統已經幫我們做好了View層面基本的恢復工作, 主要是依靠下面兩個方法:

@OverrideprotectedvoidonSaveInstanceState(Bundle outState){        super.onSaveInstanceState(outState);        // 在onStop()之前呼叫, 文件中說並不保證在onPause()的之前還是之後// 我的試驗中一般是在onPause()之後    }    @OverrideprotectedvoidonRestoreInstanceState
(Bundle savedInstanceState){ super.onRestoreInstanceState(savedInstanceState); // 在onStart() 之後 }

Bundle其中包含了activity中的view和fragment的各種資訊, 所以呼叫基類的方法就可以完成基本的view層面的恢復工作.
注意這兩個方法並不是activity的生命週期回撥, 對於activity來說它們不是一定會發生的.
另外需要注意的是, View必須要有id才能被恢復.

舉一個例項來說明:
Activity A start B, 那麼A的onSaveInstanceState()會在onStop()之前呼叫, 以防A被系統銷燬.
但是在B中按下back鍵finish()了自己後, B被銷燬的過程中, 並沒有呼叫onSaveInstanceState(), 是因為B並沒有被壓入task的back stack中,
也即系統知道B並不需要儲存自己的狀態.
正常情況下, 返回到A, A沒有被銷燬, 也不會呼叫onRestoreInstanceState(), 因為所有的狀態都還在, 並不需要重建.

如果我們打開了Do not keep activities開關, 模擬系統記憶體不足時的行為, 從A到B, 可以看到當B resume的時候A會一路走到onDestroy(),
而關掉B之後, A會從onCreate()開始走, 此時onCreate()的引數bundle就不為空了, onStart()之後會呼叫onRestoreInstanceState()方法, 其引數bundle中內容類似於如下:

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

其中包含了View的狀態, 如果有Fragment, 也會包含Fragment的狀態, 其實質是儲存了FragmentManagerState, 內容類似於如下:

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什麼時候會呼叫onSaveInstanceState()呢?
當從A開啟B之後, 按下Home鍵, B就會呼叫onSaveInstanceState().
因為這時候系統不知道使用者什麼時候會返回, 有可能會把B也銷燬了, 所以儲存一下它的狀態.
如果下次回來它沒有被重建, onRestoreInstanceState()就不會被呼叫, 如果它被重建了, onRestoreInstanceState()才會被呼叫.

Activity儲存方法的呼叫時機

activity的onSaveInstanceState()onRestoreInstanceState()方法在如下情形下會呼叫:

  1. 螢幕旋轉重建: 先save再restore.
  2. 啟動另一個activity: 當前activity在離開前會save, 返回時如果因為被系統殺死需要重建, 則會從onCreate()重新開始生命週期, 呼叫onRestoreInstanceState(); 如果沒有重建, 則不會呼叫onCreate(), 也不會呼叫onRestoreInstanceState(), 生命週期從onRestart()開始, 接著onStart()和onResume().
  3. 按Home鍵的情形和啟動另一個activity一樣, 當前activity在離開前會save, 使用者再次點選應用圖示返回時, 如果重建發生, 則會呼叫onCreate()和onRestoreInstanceState(); 如果activity不需要重建, 只是onRestart(), 則不會呼叫onRestoreInstanceState().

Activity恢復方法的呼叫時機

activity的onSaveInstanceState()onRestoreInstanceState()方法在如下情形下不會呼叫:

  1. 使用者主動finish()掉的activity不會呼叫onSaveInstanceState(), 包括主動按back退出的情況.
  2. 新建的activity, 從onCreate()開始, 不會呼叫onRestoreInstanceState().

Activity中還需要手動恢復什麼

如上, 系統已經為我們恢復了activity中的各種view和fragment, 那麼我們自己需要儲存和恢復一些什麼呢?
答案是成員變數值.

因為系統並不知道你的各種成員變數有什麼用, 哪些值需要儲存, 所以需要你自己覆寫上面兩個方法, 然後把自己需要儲存的值加進bundle裡面去. 具體例子, 這裡Activity的重新建立有, 我就不重複了.
重要的是不要忘記呼叫super的方法, 那裡有系統幫我們恢復的工作.

工具類Icepick介紹

在介紹下面的內容之前, 先介紹一個小工具: Icepick
這個工具的作用是, 在你想儲存和重建自己的成員變數資料時, 幫你省去那些put和get方法的呼叫, 你也不用為每一個欄位起一個常量key.
你需要做的就是簡單地在你想要儲存狀態的欄位上面加上一個@State 註解.
然後在儲存和恢復的時候分別加上一句話:

@OverridepublicvoidonCreate(Bundle savedInstanceState){    super.onCreate(savedInstanceState);    Icepick.restoreInstanceState(this, savedInstanceState);  }  @OverridepublicvoidonSaveInstanceState(Bundle outState){    super.onSaveInstanceState(outState);    Icepick.saveInstanceState(this, outState);  }

然後你的成員變數就有了它應該有的值了, DONE!

Fragment的狀態儲存和恢復

Fragment的狀態比Activity的要複雜一些, 因為它的生命週期狀態比較多.

Fragment狀態儲存和恢復的相關方法

按照上面的思路, 我先去查詢Fragment中儲存和恢復的回撥方法了.
Fragment的狀態儲存回撥是這個方法:

publicvoidonSaveInstanceState(Bundle outState){        // may be called any time before onDestroy()    }

這個方法和之前activity的情況大體是類似的, 它不是生命週期的回撥, 所以只在有需要的時候會調到.
onSaveInstanceState()在activity呼叫onSaveInstanceState()的時候發生, 用於儲存例項狀態.(看它的方法名: instance state).
onSaveInstanceState()方法儲存的bundle會返回給幾個生命週期回撥: onCreate()onCreateView()onViewCreated()onActivityCreated().

Fragment並沒有對應的onRestoreInstanceState()方法.
也即沒有例項狀態的恢復回撥.

Fragment只有一個onViewStateRestored()的回撥方法:

publicvoidonViewStateRestored(@Nullable Bundle savedInstanceState){        // 在onActivityCreated()和onStart()之間呼叫        mCalled = true;    }

onViewStateRestored()每次新建Fragment都會發生.
它並不是例項狀態恢復的方法, 只是一個View狀態恢復的回撥.

在這裡我先上個結論, 把檢視原始碼中Fragment狀態儲存和恢復的相關方法列出來:

Fragment狀態儲存入口:

Fragment的狀態儲存入口有三個:

  1. Activity的狀態儲存, 在Activity的onSaveInstanceState()裡, 呼叫了FragmentManger的saveAllState()方法, 其中會對mActive中各個Fragment的例項狀態和View狀態分別進行儲存.
  2. FragmentManager還提供了public方法: saveFragmentInstanceState(), 可以對單個Fragment進行狀態儲存, 這是提供給我們用的, 後面會有例子介紹這個. 其中呼叫的saveFragmentBasicState()方法即為情況一中所用, 圖中已畫出標記.
  3. FragmentManager的moveToState()方法中, 當狀態回退到ACTIVITY_CREATED, 會呼叫saveFragmentViewState()方法, 儲存View的狀態.

moveToState()方法中有很長的switch case, 中間不帶break, 基本是根據新狀態和當前狀態的比較, 分為正向建立和反向銷燬兩個方向, 一路沿著多個case走下去.

Fragment狀態恢復入口:

三個恢復的入口和三個儲存的入口剛好對應.

  1. 在Activity重新建立的時候, 恢復所有的Fragment狀態.
  2. 如果呼叫了FragmentManager的方法: saveFragmentInstanceState(), 返回值得到的狀態可以用Fragment的setInitialSavedState()方法設定給新的Fragment例項, 作為初始狀態.
  3. FragmentManager的moveToState()方法中, 當狀態正向建立到CREATED時, Fragment自己會恢復View的狀態.

這三個入口分別對應的情況是:
入口1對應系統銷燬和重建新例項.
入口2對應使用者自定義銷燬和建立新Fragment例項的狀態傳遞.
入口3對應同一Fragment例項自身的View狀態重建.

Fragment狀態儲存恢復和Activity的聯絡

這裡對應的是入口1的情況.
當Activity在做狀態儲存和恢復的時候, 在它其中的fragment自然也需要做狀態儲存和恢復.
所以Fragment的onSaveInstanceState()在activity呼叫onSaveInstanceState()的時候一定會發生.
同樣的, 如果Fragment中有一些成員變數的值在此時需要儲存, 也可以用@State標記, 處理方法和上面一樣.
也即, 在Activity需要儲存狀態的時候, 其中的Fragments的例項狀態自動被處理儲存.

Fragment同一例項的View狀態恢復

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

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

privatevoidinitFragments(){    tab1Fragment = getFragmentManager().findFragmentByTag(Tab1Fragment.TAG);    if (tab1Fragment == null) {        tab1Fragment = newTab1Fragment();    }    tab2Fragment = getFragmentManager().findFragmentByTag(Tab2Fragment.TAG);    if (tab2Fragment == null) {        tab2Fragment = newTab2Fragment();    }}

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

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

可以看到, 每一次的切換, 都是一個Fragment的完全destroy, detach和另一個fragment的attach, create,
但是當我在這兩個fragment中各自加上EditText, 發現只要EditText有id, 切換過程中EditText的內容是被儲存的.
這是誰在什麼時候儲存並恢復的呢?
我在TextChange的回撥裡打了斷點, 發現呼叫棧如下:

FragmentManagerImpl中, moveToState()方法的case Fragment.CREATED中:
呼叫了: f.restoreViewState(f.mSavedFragmentState);
此時我沒有做任何儲存狀態的處理, 但是斷點中可以看出:

雖然mSavedFragmentState是null, 但是mSavedViewState卻有值.
所以這個View狀態儲存和恢復對應的入口即是上面兩個圖中的入口三.

這是因為我的兩個fragment只new了一次, 然後儲存了成員變數, 即便是Fragment重新onCreate(), 但是對應的例項仍然是同一個.
這和Activity是不同的, 因為你是無法new一個Activity的.

在上面的例子中, 如果不儲存Fragment的引用, 每次都new Fragment, 那麼View的狀態是不會被儲存的, 因為不同例項間的狀態傳遞只有在系統銷燬恢復的情況下才會發生(入口一).
如果我們需要在不同的例項間傳遞狀態, 就需要用到下面的方法.

不同Fragment例項間的狀態儲存和恢復

這裡對應的是入口2, 不同於入口1和3, 它們是自動的, 入口2是使用者主動儲存和恢復的情形.
自己主動儲存Fragment的狀態, 可以呼叫FragmentManager的這個方法:

publicabstract Fragment.SavedState saveFragmentInstanceState(Fragment f);

它的實現是這樣的:

@Overridepublic Fragment.SavedStatesaveFragmentInstanceState(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;    }    returnnull;}

返回的資料型別是: Fragment.SavedState, 這個state可以通過Fragment的這個方法設定給自己:

publicvoidsetInitialSavedState(SavedState state){    if (mIndex >= 0) {        thrownew IllegalStateException("Fragment already active");    }    mSavedFragmentState = state != null && state.mState != null            ? state.mState : null;}

但是注意只能在Fragment被加入之前設定, 這是一個初始狀態.
利用這兩個方法可以更加自由地儲存和恢復狀態, 而不依賴於Activity.
這樣處理以後, 不必儲存Fragment的引用, 每次切換的時候雖然都new了新的例項, 但是舊的例項的狀態可以設定給新例項.

例子程式碼:

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

注意這裡用了SparseArray來儲存Fragment的狀態, 並且加上了@State, 這樣在Activity重建的時候其中的內容也能夠被恢復.

Back stack中的fragment

有一點很特殊的是, 當Fragment從back stack中返回, 實際上是經歷了一次View的銷燬和重建, 但是它本身並沒有被重建.
即View狀態需要重建, 例項狀態不需要重建.

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

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

Fragment setRetainInstance

注意這個方法只是針對configuration change, 並不影響使用者主動關閉和系統銷燬的情況:
當activity被使用者主動finish, 其中的所有fragments仍然會被銷燬.
當activity不在最頂端, memory不夠了, 系統仍然可能會銷燬activity和其中的fragments.

View的狀態儲存和恢復

View的狀態儲存和恢復主要是依賴於下面幾個方法:
儲存: saveHierarchyState() -> dispatchSaveInstanceState() -> onSaveInstanceState()
恢復: restoreHierarchyState() -> dispatchRestoreInstanceState() -> onRestoreInstanceState()
還有兩個重要的前提條件是View要有id, 並且setSavedEnabled()為true.(這個值預設為true).
在系統的widget裡(比如TextView, EditText, Checkbox等), 這些都是已經被處理好的, 我們只需要給View賦予id, Activity和Fragment重建的時候會自動恢復其中的狀態. (這裡的Fragment恢復對應入口一和入口三, 入口二屬於跨例項新建的情況).

但是如果你要使用第三方的自定義View, 就需要確認一下它們內部是否有狀態儲存和恢復的程式碼.
如果不行你就需要繼承該自定義View, 然後實現這兩個方法:

//// Assumes that SomeSmartButton is a 3rd Party view that// View State Saving/Restoring are not implemented internally//publicclassSomeBetterSmartButtonextendsSomeSmartButton{    ...    @Overridepublic Parcelable onSaveInstanceState(){        Bundle bundle = newBundle();        // Save current View's state herereturn bundle;    }    @OverridepublicvoidonRestoreInstanceState(Parcelable state){        super.onRestoreInstanceState(state);        // Restore View's state here    }    ...}
WebView的狀態儲存和恢復

WebView的狀態儲存和恢復不像其他原生View一樣是自動完成的.
WebView不是繼承自View的.
如果我們把WebView放在佈局裡, 不加處理, 那麼Activity或Fragment重建的過程中, WebView的狀態就會丟失, 變成初始狀態.

在Fragment的onSaveInstanceState()裡面可以加入如下程式碼來儲存WebView的狀態:

@OverridepublicvoidonSaveInstanceState(Bundle outState){    super.onSaveInstanceState(outState);    webView.saveState(outState);}

然後在初始化的時候, 增加判斷, 不必每次都開啟初始連結:

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

這樣處理以後, 在重新建立的時候, WebView的狀態就能恢復到離開前的頁面.
不論WebView是放在Activity裡還是Fragment裡, 這個方法都適用.

但是Fragment還有另一種情況, 即Fragment被壓入back stack, 此時它沒有被destroy(), 所以沒有呼叫onSavedInstanceState()這個方法.
這種情況返回的時候, 會從onCreateView()開始, 並且savedInstanceState為null, 於是其中WebView之前的狀態在此時丟失了.
解決這種情況可以利用Fragment例項並未銷燬的條件, 增加一個成員變數bundle, 儲存WebView的狀態, 最終解決如下:

private Bundle webViewState;@OverridepublicvoidonViewCreated(View view, Bundle savedInstanceState){    super.onViewCreated(view, savedInstanceState);    ButterKnife.bind(this, view);    initWebView();    if (webViewState != null) {        //Fragment例項並未被銷燬, 重新create view        webView.restoreState(webViewState);    } elseif (savedInstanceState != null) {        //Fragment例項被銷燬重建        webView.restoreState(savedInstanceState);    } else {        //全新Fragment        webView.loadUrl(TEST_URL);    }}@OverridepublicvoidonPause(){    super.onPause();    webView.onPause();    //Fragment不被銷燬(Fragment被加入back stack)的情況下, 依靠Fragment中的成員變數儲存WebView狀態    webViewState = new
            
           

相關推薦

Fragment狀態儲存恢復

前言 我們知道,在activity中,當配置發生改變,比如螢幕方向發生變化時,activity會被銷燬,然後重新建立。在activity中有兩個方法用於儲存和恢復狀態,分別是: @Override protected void onSaveInsta

Android Fragment使用(三) Activity, Fragment, WebView狀態儲存恢復

Android中的狀態儲存和恢復 Android中的狀態儲存和恢復, 包括Activity和Fragment以及其中View的狀態處理. Activity的狀態除了其中的View和Fragment的狀態之外, 還需要使用者手動儲存一些成員變數. Fragment的狀態有它自己的例項狀態和其中的View狀態,

Activity, Fragment, WebView狀態儲存恢復

Android中的狀態儲存和恢復 Android中的狀態儲存和恢復, 包括Activity和Fragment以及其中View的狀態處理. Activity的狀態除了其中的View和Fragment的狀態之外, 還需要使用者手動儲存一些成員變數. Fragment的狀態有它自己的例項狀態和其中的View狀態,

安卓效能優化之ActivityFragment通過onSaveInstanceState()儲存恢復資料

Activity和Fragment 都有自己的生命週期,而且很類似.Fragment比Activity多了onAttach()和onCreateView()這些方法.整體它們兩者是一樣的週期,都會經歷從建立檢視( onCreate(),onCreateView(),onSt

Android繪圖之Canvas狀態儲存恢復(7)

1 Canvas 狀態儲存和恢復 前面講canvas概念理解時 已經講解了save和savelayer,saveLayerAlpha函式,這裡進行canvas狀態儲存和恢復的詳細講解。 Canvas 呼叫了translate,scale,rotate,skew,concat or

[譯]Android Activity Fragment 狀態儲存恢復的最佳實踐

譯者亦楓注:對於 Activity、Fragment 和 View 是如何儲存與恢復狀態的問題,相信很多開發人員都處於一知半解的狀態。最近剛好在總結 Fragment 的使用注意事項,無意中從網上看到國外的一篇好文,對這個問題做了一個全面的解析。加之使用視

activity/fragment view的儲存恢復

儲存/恢復 activity和fragment 一、activity 當Activity的onSaveInstanceState被呼叫的時候,Activity將會從View 層次(View Hierachy)中的每一個View中自動蒐集View的狀態。請注意,只會蒐集實現了View狀態儲存/

Canvas繪圖狀態儲存恢復(十)

首先,什麼是狀態,畫布上的路徑和點陣圖並不屬於狀態,應該把狀態看做2D渲染上下文屬性的描述;是不是很難理解!!! 那就別理解了,看以下的例子你能基本理解這個意思!!! 1、儲存繪圖狀態函式   context.save(); 儲存當前畫布狀態 程式碼使用:  

Android異常退出時Activity資料的儲存恢復

本文章是基於Kotlin版的簡單Activity-Fragment狀態切換及資料保留的探討,原問題如下: 頁面長時間放置後臺,或者在其他頁面crash後,退到主頁面,發現智護頁面出現重疊。 該頁面架構簡單:主Activity對兩個Fragment,一個智護Fr

【QT】如何使用savestate()restoreState()來儲存恢復工具條,狀態列,其它檢視等的頁面佈局

如何使用savestate()和restoreState()來儲存和恢復工具條,狀態列,其它檢視等的頁面佈局 運用場景:建立一個基於QMainWindow的QT Widgets Application,然後根據需要新增選單欄、工具欄、狀態列等等;這是工具欄有很多,好多都疊在一起,經過拖拽

Android中Fragment資料儲存恢復

原文地址:請掃文後stormzhang大神的微信公眾號——AndroidDeveloper 寫在前面 上週我們總結了Activity中資料的儲存和恢復,我們花兩分鐘來回顧一下: 一句話總結 臨時資料 對於臨時資料,我們使用onSaveInstanceStat

tensorflow saver 儲存恢復指定 tensor

在實踐中經常會遇到這樣的情況: 1, 用簡單的模型預訓練引數 2, 把預訓練的引數匯入複雜的模型後訓練複雜的模型 這時就產生一個問題:            &nb

將圖片檔案以二進位制方式儲存恢復

/** * 將圖片轉換成二進位制 * * @return */ static String getImageBinary() { BASE64Encoder encoder = new sun.misc.BASE64Encoder(); //本地圖片 Fil

pickle模組以特殊的二進位制格式儲存恢復資料物件

先用pickle模組進行資料物件的儲存 1 import pickle 2 3 data1 = {'a': [1, 2, 3, 9], 4 'b': ('string', 'Unicode string'), 5 'c': ('True',

sklearn模型的儲存恢復

在做模型訓練的時候,尤其是在訓練集上做交叉驗證,通常想要將模型儲存下來,然後放到獨立的測試集上測試,下面介紹的是Python中訓練模型的儲存和再使用。 scikit-learn已經有了模型持久化的操作,匯入joblib即可 from sklearn.externals import joblib

【Tensorflow】資料及模型的儲存恢復

如果你是一個深度學習的初學者,那麼我相信你應該會跟著教材或者視訊敲上那麼一遍程式碼,搭建最簡單的神經網路去完成針對 MNIST 資料庫的數字識別任務。通常,隨意構建 3 層神經網路就可以很快地完成任務,得到比較高的準確率。這時候,你信心大增,準備挑戰更難的任務。

儲存恢復神經網路

轉自莫煩大神,轉載原因是想把所有相關內容收集到自己的部落格中,方便系統的學習。 兩種儲存方法,1是儲存整個神經網路;2是隻儲存神經網路的所有引數。 一、儲存神經網路 1儲存整個神經網路。 torch.save(net1,"net1.pkl") net1為我想要儲存的網路,net1.pkl

雲風協程庫儲存恢復協程執行棧原理講解

   首先, linux下的程序地址空間佈局是這樣子的: 可以看到 整個程序地址空間從上到下地址變化是從高地址到低地址的! 32 位系統有 4G 的地址空間,其中0x08048000-> 0xbfffffff 是使用者空間,0xc0000000~0xffffffff 是核

簡單完整地講解tensorflow模型的儲存恢復

http://blog.csdn.net/liangyihuai/article/details/78515913 在本教程主要講到: 1. 什麼是Tensorflow模型? 2. 如何儲存Tensorflow模式? 3. 如何還原預測/遷移學習Tensorflow模型? 4. 如

QT使用saveState()restoreState()函式儲存恢復介面佈局

簡介:每次當我們自己寫的程式執行起來時,我們把介面調整到我們所喜歡的佈局。但是當我們把程式關閉了,下次重啟程式時,我們之前調整的介面佈局沒有了,恢復到了QT自預設的介面的介面佈局。這對於有我們操作非常不方便,還好QT提供了儲存介面佈局和恢復介面佈局的介面,我們只需要呼叫一下介