fragmentactivity中fragment界面錯亂問題

 
 

[Vio.wang 崇尚開源 歡迎點評]
原本是打算將此問題記載到問題反饋中,可是感受涉及到的面偏大,就單寫一篇吧。
其實這也算的上是一個比較常見的問題了,APP被回收以後,從新回到前臺時,頁面Activity會被從新加載,其中必然涉及到了onSaveInstanceState()及 onRestoreInstanceState()兩個方法,都懂得,你們都是資深猿。
剛開始發現這個問題其實也蠻詫異的,這也算是google沒考慮到的吧,扯遠了。網上關於這個問題有兩個解決方案,以下:
(1)重寫onSaveInstanceState方法,將調用父類的方法給幹掉。此招毒辣,釜底抽薪,不失優雅。java

  @Override
    protected void onSaveInstanceState(Bundle outState) {
//        super.onSaveInstanceState(outState);
        outState.putInt("mLastIndex", mLastIndex);

    }

 

讓咱們看看父類中是如何進行處理的,又爲什麼須要把它給幹掉。數組

/** * 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); } }

因爲Activity繼承了FragmentActivity,FragmentActivity默認就執行次方法,在頁面被回收時,保存了全部已加載的fragment狀態。
再看看其onCreate()app

if (savedInstanceState != null) { Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG); mFragments.restoreAllState(p, nc != null ? nc.fragments : null); } mFragments.dispatchCreate();

在FragmentActivity的onCreate中又默認恢復了當前保存的fragment.
這裏就能夠看出fragment加載混亂的根本緣由了,FragmentActivity幫咱們管理了當前的fragment,而咱們在本身的Activity中沒有作判斷就直接添加視圖,因此很顯然會出現問題。
或許你會說,我作了判斷啊,那咱們來看看第二種解決方法:
(2)第二種方法即是找到咱們的getSupportFragmentManager中的已添加的fragment。
首先在add Fragment時調用如下方法,給Fragment添加一個tag(tag建議給一個fragmentTags的數組)。ide

public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment, @Nullable String tag);

 

而後在onCreate中判斷savedInstanceState != null 時根據tag在getSupportFragmentManager中從新拿到fragment,如:ui

aroundFragment = (AroundFragment) manager.findFragmentByTag(fragmentTags[0]);

這樣也能夠解決問題,有人說不行,請多嘗試一二。
(3)這種方法,提及來也是把我坑苦了,因爲項目須要集成融雲,直接複用了融雲的會話列表UI。集成過RC的人可能知道,RC的會話列表加載方式是經過動態Uri的方式加載。這樣的話,第一種方式就不能用了,與RC衝突,第二種方式一樣也不理想,也出了問題,頁面被回收以後,從新加載回來會話列表爲空,呃。。。森森的受傷了。。。
因而,便研究起了getSupportFragmentManager的管理策略,個人想法就是講棧中全部的fragment清空,從新加載一遍,應該就不會有問題了。
那麼,怎麼清空棧呢?��http://stackoverflow.com/questions/6186433/clear-back-stack-using-fragments
在這裏記錄一下:
清空棧:google

FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) { fm.popBackStack(); }

推出某fragment及以上的fragmentspa

FragmentManager.popBackStack(XX.class.getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE)

而後,咱們一樣須要在判斷if (savedInstanceState != null) {}中將全部的fragment置空:rest

@Override protected void init(Bundle savedInstanceState) { setContentView(R.layout.activity_main); FragmentManager manager = getSupportFragmentManager(); if (savedInstanceState != null) { mLastIndex = savedInstanceState.getInt("mLastIndex", 0); //fragmentmanager將棧中全部在ConversationListFragment之上的fragment推出 // manager.popBackStack(ConversationListFragment.class.getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE); for (int i = 0; i < manager.getBackStackEntryCount(); ++i) { manager.popBackStack(); } conversationListFragment = null; ...... }

問題至此解決。。。code

相關文章
相關標籤/搜索