1. 程式人生 > >Android重新開啟APP應用程式或activity後fragment 重疊問題

Android重新開啟APP應用程式或activity後fragment 重疊問題

問題發生的場景:

螢幕旋轉
activity被強殺後重啟
應用在後臺被擠出後重新開啟
。。。

產生原因:

FragmentState沒有儲存隱藏還是顯示這個狀態,當生命週期又走一次的時候又建立了一次fragment,所以導致重疊
解決方法1:

(太low,不推薦使用。不能恢復重啟前的介面)

直接在包含Fragment的Activity中複寫onSaveInstanceState()方法,使其空實現;(在BaseActivity實現)不傳遞任何資訊,自然不會恢復fragment,也就沒有重疊了,全部重新建立一次

@Override  
 protected void onSaveInstanceState(Bundle outState) {  
   //super.onSaveInstanceState(outState);  
 }

解決方法2:

(牆裂推薦)
onSaveInstanceState儲存狀態,根據需要恢復。有findTag肯定就有setTag的地方。

 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initFragments();
        if (savedInstanceState!=null){
            mRadioGroup.setOnCheckedChangeListener(this);
            mIndex = savedInstanceState.getInt(CURRENT_INDEX, 0);
            hideFragment();
        }else {
            initRadioGroupChecked();
        }
    }

    private void hideFragment() {
        FragmentManager supportFragmentManager = getSupportFragmentManager();
        mHomeFragment= (HomeFragment) supportFragmentManager.findFragmentByTag(HomeFragment.class.getName());
        mInvestFragment= (InvestFragment) supportFragmentManager.findFragmentByTag(InvestFragment.class.getName());
        mFindFragment= (FindFragment) supportFragmentManager.findFragmentByTag(FindFragment.class.getName());
        mMyFragment= (MyFragment) supportFragmentManager.findFragmentByTag(MyFragment.class.getName());
        FragmentTransaction transaction = supportFragmentManager.beginTransaction();
        if (mHomeFragment!=null) transaction.hide(mHomeFragment);
        if (mInvestFragment!=null) transaction.hide(mInvestFragment);
        if (mFindFragment!=null) transaction.hide(mFindFragment);
        if (mMyFragment!=null) transaction.hide(mMyFragment);
        transaction.commit();
    }

    private void initRadioGroupChecked() {
        mRadioGroup.setOnCheckedChangeListener(this);
        mRadioGroup.check(R.id.rb_home);
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction ft = fragmentManager.beginTransaction();
        ft.add(R.id.fragment_container, mSparseArray.get(0),mSparseArray.get(0).getClass().getName()).show(mSparseArray.get(0));
        ft.commit();
    }

    @Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        outState.putInt(CURRENT_INDEX,mIndex);
        super.onSaveInstanceState(outState);
    }

不知你們發現沒有,在hideFragment方法裡面明明把所有的fragment都隱藏了,但是重新開啟應用還是呈現出退出之前的介面,因為我使用了有兩個形參的onSaveInstanceState方法。PersistableBundle 就是用來做資料持久化的,所有還是顯示上一場退出的那個介面。此時呈現的介面其實是新建的,而不是之前的,之前的已經被隱藏了。當然也可以使用只有一個形參的onSaveInstanceState方法。但是就要自己手動再show一個新的fragment出來。可能有人覺得在hideFragment不隱藏就好了,但是切換的時候還是要用findFragmentByTag找出來再隱藏,不然還是有重疊的問題。

解決方法3:

(方法3思路是最高階的,但還是推薦方法2)

在basefragment中重寫onSaveInstanceState,既然系統沒儲存那就手動儲存

private String FRAGMENT_STATE="fragment_state";
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState!=null){
        boolean isHidden = savedInstanceState.getBoolean(FRAGMENT_STATE, false);
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        if (isHidden){
            transaction.hide(this);
        }else {
            transaction.show(this);
        }
        transaction.commit();
    }

}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean(FRAGMENT_STATE,isHidden());
}

然後會發現在主activity切換fragment的時候還是會有重疊問題。因為你在切換的時候可能做了隱藏的操作,但是其實你隱藏的是新new出來的fragment,而不是重啟之前的fragment。所以還是要在主activity的oncreate中做判斷然後寫方法2中的hideFragment方法。所以我還是推薦方法2.

總結

如果你是想解決在APP主介面底部按鈕切換fragment導致的重疊問題選擇方法2。如果你只是單純的多個fragment造成的重疊問題可以選擇方法3。