1. 程式人生 > >activity被回收,fragment恢復處理

activity被回收,fragment恢復處理

例如activity放在後臺一段時間,當activity被回收之後,再重新進入activity的時候,會重新呼叫onCreate(),並且savedInstanceState不再是null,因此可以判斷出是否被回收。

onCreate中不要重複建立fragment,通過tag去獲得figment即可。

從谷歌開源專案中得到的的啟示,原始碼:

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getContentViewResId());

        if (getIntent().hasExtra(Intent.EXTRA_TITLE)) {
            setTitle(getIntent().getStringExtra(Intent.EXTRA_TITLE));
        }

        final String customTitle = getIntent().getStringExtra(Intent.EXTRA_TITLE);
        setTitle(customTitle != null ? customTitle : getTitle());

        if (savedInstanceState == null) {
            mFragment = onCreatePane();
            mFragment.setArguments(intentToFragmentArguments(getIntent()));
            getFragmentManager().beginTransaction()
                    .add(R.id.root_container, mFragment, "single_pane")
                    .commit();
        } else {
            mFragment = getFragmentManager().findFragmentByTag("single_pane");
        }
    }
原始碼摘自:
com.google.samples.apps.iosched.ui.SimpleSinglePaneActivity

自己精簡一下就是:

public class MainActivity extends AppCompatActivity {
    private BlankFragment mFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (savedInstanceState == null) {
            mFragment = new BlankFragment();
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.root_container, mFragment, "single_pane")
                    .commit();

        } else {
            mFragment = (BlankFragment) getSupportFragmentManager().findFragmentByTag("single_pane");
        }
        Log.e("MainActivity", "savedInstanceState=" + savedInstanceState + " mFragment=" + mFragment);
    }
}

列印了兩個Log,一個是首次建立,另一個是回收了之後建立。

11-22 12:55:43.940 24433-24433/com.example.baidu.test E/MainActivity: savedInstanceState=null mFragment=BlankFragment{585c98a id=0x7f0b0055 single_pane}

11-22 12:57:36.576 24433-24433/com.example.baidu.test E/MainActivity: savedInstanceState=Bundle[{android:viewHierarchyState=Bundle[mParcelledData.dataSize=680], android:support:
[email protected]
}] mFragment=BlankFragment{baa458c #0 id=0x7f0b0055 single_pane}

測試的時候可以設定手機【不保留活動】,這樣可以快速的模擬回收的情況,小米手機有這個功能。

Activity被回收,系統為什麼會儲存Fragment呢?來分析一下FragmentActivity原始碼:

/**
     * Save all appropriate fragment state.
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Parcelable p = mFragments.saveAllState();
        if (p != null) {
            outState.putParcelable(FRAGMENTS_TAG, p);//這裡儲存了Fragment資料
        }
        if (mPendingFragmentActivityResults.size() > 0) {
            outState.putInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG, mNextCandidateRequestIndex);

            int[] requestCodes = new int[mPendingFragmentActivityResults.size()];
            String[] fragmentWhos = new String[mPendingFragmentActivityResults.size()];
            for (int i = 0; i < mPendingFragmentActivityResults.size(); i++) {
                requestCodes[i] = mPendingFragmentActivityResults.keyAt(i);
                fragmentWhos[i] = mPendingFragmentActivityResults.valueAt(i);
            }
            outState.putIntArray(ALLOCATED_REQUEST_INDICIES_TAG, requestCodes);
            outState.putStringArray(REQUEST_FRAGMENT_WHO_TAG, fragmentWhos);
        }
    }
從原始碼中得知,當Activity呼叫onSaveInstanceState方法的時候,會儲存當前Activity裡面的所有Fragment,儲存在了一個Bundle裡,key就是FRAGMENTS_TAG。
其實這個Bundle會在Activity恢復的時候傳給onCreate,這就是為什麼onSaveInstanceState不是null了。 有人會問什麼時候會呼叫onSaveInstanceState方法?用最簡潔的一句話:當Activity不可見的時候就會執行nSaveInstanceState。例如被另一個Activity覆蓋,按Home鍵回到桌面等等。當然你主動結束Activity不會執行。呼叫onSaveInstanceState儲存的不只是fragment,還儲存了View的狀態,只儲存了帶id的View的狀態,不帶id不會儲存的。 其實回收之後恢復是很麻煩的,得到了Fragment後,你會發現成員變數並沒有恢復,只有View某些狀態被恢復了,如果完全重現被回收那一刻的所有狀態,還需要考慮在Fragment裡面重寫onSaveInstanceState方法,來儲存一些資料,呵呵,工作量不小啊,非特殊情況下,我不建議這麼做。 我一般的做法都是重新建立Activity和Fragment:
public class MainActivity extends AppCompatActivity {
    static final String FRAGMENTS_TAG = "android:support:fragments";
    private BlankFragment mFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //刪除儲存的Fragment,也可以重寫onSaveInstanceState方法不讓其儲存
        if (savedInstanceState != null) {
            savedInstanceState.putParcelable(FRAGMENTS_TAG, null);
        }
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mFragment = new BlankFragment();
        getSupportFragmentManager().beginTransaction()
                .add(R.id.root_container, mFragment, "single_pane")
                .commit();
    }
}

你可以記住重要的關鍵資訊,來恢復這個Activiy。例如當前Activity是一篇文章,你只需要在onSaveInstanceState儲存文章id,等恢復的時候直接根據id從伺服器拉取就好了。

如果你的Activity在啟動時的Intent裡面有文章id,那就簡單了,在回收恢復的時候,直接這樣仍然得到文章id:String id = getIntent().getStringExtra("article_id");,這樣根本不用你主動儲存。使用Intent的時候必須序列化的原因:只有被序列化的物件和基本資料型別才可以儲存在磁碟上,這樣記憶體被幹掉,仍然可以將他們從磁碟上恢復到記憶體中。

相關推薦

activity回收fragment恢復處理

例如activity放在後臺一段時間,當activity被回收之後,再重新進入activity的時候,會重新呼叫onCreate(),並且savedInstanceState不再是null,因此可以判斷出是否被回收。 onCreate中不要重複建立fragment,通過

關於fragmentactivity回收之後重新恢復

當記憶體不足的時候位於後臺的應用會被系統回收掉,只是保留著任務棧,再次進入的時候會恢復它們。 要注意的地方有:系統只會把ui相關的東西存起來和恢復,其他的一些成員變數都不會管。 會把生命週期和建立一樣重新走一遍,這個時候得注意那些不是從onCreat這樣的生命週期方法中獲得

activity回收點選Tab無法切換fragment

1、原因:當activity在後臺並且記憶體不足時,系統會把activity給回收掉,但也會儲存部分(不是全部)資訊用於下次頁面恢復。這樣會導致下次進入頁面後佈局或資料錯亂,並且點選底部Tab無法切換fragment。 2、解決方法: (1)方法一:註釋掉sup

Activity回收掉之後的網路請求回撥處理方法詳解

想起寫這麼一篇博文的前提是上週去面試了一家公司,其中有這麼一個問題印象深刻,結合當時在網上看到的解決辦法我就說了一個錯誤答案,結果當場就被面試官給指出了錯誤,所以回來後和我的領導一起討論了這麼一個問題,他提出了一個很好地解決思路,於是乎我便寫了這麼一段程式

Activity回收導致繫結Fragment呼叫getActivity()拋空指標異常

當系統記憶體不足,Fragment的宿主Activity被回收的時候,Fragment的例項並沒有隨之被回收。Activity被系統回收時,會主動呼叫onSaveInstance()方法來儲存檢視層(

Activity回收掉之後的網路回撥處理

早上來到公司剛開啟電腦,就被叫到會議室,召開緊急會議,線上出現重大bug,根據線上日誌統計,崩潰率上升了0.3個百分點(我們專案是集成了騰訊Bugly統計日誌,有興趣的同學可以去了解下)。 這個可不得了,聽說領導被老闆叫過去訓了好久,領導憋了一肚子火,我們的日

Activity在後臺回收這個時候觸發showDialog窗體洩露WindowManager.BadTokenException

今天在友盟上看到一個崩潰日誌,如下: android.view.WindowManager$BadTokenException: Unable to add window -- token [email protected] is not valid; is y

程式後臺Activity回收後再次啟動fragment失效問題

/////////////////2016/07/01///////////////////// /////////////////by  xbw////////////////////////// /////////////////環境  eclipse///////////////// 先上個圖,

activity改變時我們如何處理

速度 change 假設 IT super conf In develop aras 用戶和系統觸發-的事件,可能造成一個activity狀體的改變。這個文檔描述了一些常見的情況,和如何去處理這些改變。 原網站:https://developer.android.googl

桌面的Internet圖示刪除如何恢復

桌面的Internet圖示被刪除,如何恢復 有時候桌面的Internet圖示被刪除了,一時又不知如何還原。下面簡單介紹幾種方法。 方法一:在桌面右擊,屬性,桌面,自定義桌面,勾選Internet,確定。當然有人會說,我的自定義桌面裡沒有Internet選項,這是由於系統的兩

系統排錯2:若mbr載入程式破壞如何恢復

系統排錯 若mbr載入程式被破壞,如何恢復? (1)檢視系統版本和boot載入程式所在分割槽 ##檢視系統版本 [[email protected] ~]# hostnamectl ##檢視boot載入程式所在分割槽 [[email protect

後臺的activity系統自動回收的話怎麼在回到介面的時候恢復資料

 Activity的狀態通常情況下系統會自動儲存的,只有當我們需要儲存額外的資料時才需要使用到這樣的功能。 通常情況:  呼叫onPause()和onStop()方法後的activity例項仍然存在

Activity巢狀多個fragmentonResume的處理

問題:當Activity裡有多個fragment時,其中fragmentA根據需求,需要在onResume時需要做請求資料等操作,但是如果直接在fragmentA裡的onResume裡寫東西,當從其他頁面返回到fragmentB和fragmentC時,fragmentA裡

android FragmentActivity交互互相發數據(附圖具體解釋)

oncreate @+ targe save inflate find enter 提交 ransac 筆者最近看官方training。發現了非常多實用又好玩的知識。當中。fragment與Activity通信就是一個。 fragment與Activity通信主要

回收站清空了如何恢復數據?

展現 進入 edi 點擊 專業 類型 選項 回收 教程 不知道大家是否跟小編一樣,有定期清理回收站的習慣,但是如果回收站有重要文件但是已經清空,那麽如何把刪除的文件恢復回來呢?因為文件制作的時間過長,建議用專業的數據恢復軟件進行嘗試。在用EasyRecovery數據恢復軟件

一個Activity中多個Fragment個別fragment實現沉浸式狀態列

                如上圖,同一個activity(NoActionBar)有多個fragment的情況下,只有"我的"模組需要設定為沉浸式的狀態列,而其他fragmen

任務排程框架quartz使用總結(異常處理解決恢復後多次排程處理)

任務排程框架quartz使用總結(異常處理,解決恢復後多次排程處理)      首先先說說什麼是排程框架,大白話所謂的排程框架你可以把它看成一個定時任務管理框架,並且quartz框架是多執行緒的, quartz最主要的三大基本特性: (1)排程器&nbs

Go 語言的下一個大版本:Go 2.0 安排上了(全面相容1.X改進錯誤處理和泛型這兩大主題)

今年 8 月 Go 開發團隊公佈了 Go 2.0 的設計草案,包括錯誤處理和泛型這兩大主題。現在備受矚目的 Go 2.0 又有了新動向 —— 昨日 Go 開發團隊在其官方部落格表示,Go 2 已經被安排上了!目前 Go 2 已進入確定變更提案的階段,並公佈了提案評估流程。 廢話不多說,先

Go 語言的下一個大版本:Go 2.0 安排上了(全面兼容1.X改進錯誤處理和泛型這兩大主題)

.org leader utf8 驅動 cleanup 周期 一份 早期 下一個 今年 8 月 Go 開發團隊公布了 Go 2.0 的設計草案,包括錯誤處理和泛型這兩大主題。現在備受矚目的 Go 2.0 又有了新動向 —— 昨日 Go 開發團隊在其官

監控硬盤與普通硬盤有什麽分別刪除視頻恢復方法。

發生 添加 臺式機 用戶 視頻恢復 嘗試 慢啟動 啟動 錄制 硬盤對於每一位用戶而言都不陌生,不管是DIY裝機還是日常安防監控都有硬盤的身影,隨著PC用戶對硬件需求的提升,我們生活中出現了機械硬盤、固態硬盤等多種存儲設備。 其中,相信每一玩家在購買大容量機械硬盤的過程中都會