FragmentTransaction與addToBackStack與popBackStack

引言:這篇文章,記錄了下FragmentTransaction的使用注意事項(xiàng),和分析了下addToBackStack實(shí)際作用于誰。

public class MainActivity extends AppCompatActivity implements ItemFragment.OnListFragmentInteractionListener{
    FragmentTransaction fragmentTransaction;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.container, BlankFragment.newInstance("",""), "blank");
        fragmentTransaction.add(R.id.container, BlankFragment2.newInstance("",""), "list");
//        fragmentTransaction.addToBackStack("blank");
//        fragmentTransaction.addToBackStack("list");
        fragmentTransaction.addToBackStack("cccc");
        fragmentTransaction.commit();
    }

    @Override
    public void onListFragmentInteraction(DummyContent.DummyItem item) {

    }

    @OnClick({R.id.button1, R.id.button2})
    protected void onClick(View v){
        switch (v.getId()){
            case R.id.button1:
                getSupportFragmentManager().popBackStack();
                break;
            case R.id.button2:
                Toast.makeText(this, "button2", Toast.LENGTH_LONG).show();
                FragmentTransaction f = getSupportFragmentManager().beginTransaction();
                f.replace(R.id.container, ItemFragment.newInstance(10), "list");
                f.addToBackStack("list");
                f.commit();
//                fragmentTransaction.commit();
/*                getSupportFragmentManager().beginTransaction().add(R.id.container, ItemFragment.newInstance(10), "list");
                getSupportFragmentManager().beginTransaction().addToBackStack("list");
                getSupportFragmentManager().beginTransaction().commit();*/
                break;
        }
    }
}

1.FragmentTransaction注意的地方
1.每次fragmentManager.beginTransaction()得到的都是一個(gè)新實(shí)例。像下面對FragmentTransaction改動(dòng)的代碼是不會(huì)生效的。

 getSupportFragmentManager().beginTransaction().add(R.id.container, ItemFragment.newInstance(10), "list");
 getSupportFragmentManager().beginTransaction().addToBackStack("list");
 getSupportFragmentManager().beginTransaction().commit();

2.每次對FragmentTransaction更改后需要commit來執(zhí)行。但是這里有個(gè)要注意的地方就是,每個(gè)FragmentTransaction實(shí)例commit其實(shí)只能執(zhí)行一次。如果將上圖中的fragmentTransaction保存為全局后,當(dāng)?shù)谝淮蝐ommit后。在其他地方再去調(diào)用commit()就會(huì)報(bào)錯(cuò)(比如我在button2里去再次調(diào)用)。

protected void onCreate(Bundle savedInstanceState) {
      ...
      fragmentTransaction.commit();
}

@OnClick({R.id.button1, R.id.button2})
protected void onClick(View v){
    switch (v.getId()){
      ...
       case R.id.button2:
        ...
        fragmentTransaction.commit();
        ...
    }
...

所以說第一次更改Fragment時(shí),務(wù)必將所有的操作做完,再commit。

2.addToBackStack與popBackStack
addToBackStack其實(shí)針對的是fragmentTransaction。而非是具體的fragment。分析如下:(R.id.container是一個(gè)垂直的線性布局)從上圖調(diào)用addToBackStack部分代碼來看,我開始使用

fragmentTransaction.add(R.id.container, BlankFragment.newInstance("",""), "blank");
fragmentTransaction.add(R.id.container, BlankFragment2.newInstance("",""), "list");
fragmentTransaction.addToBackStack("list");
fragmentTransaction.commit();

當(dāng)我點(diǎn)擊button1,調(diào)用popBackStack()后,按照原先設(shè)想(addToBackStack是針對具體的fragment),那么應(yīng)該是BlankFragment2被彈出,消失。但實(shí)際結(jié)果是BlankFragment和BlankFragment2都消失了。
當(dāng)將addToBackStack("list")改成addToBackStack("blank"),結(jié)果依然是兩個(gè)fragment都消失了。
這時(shí)我就懷疑,其實(shí)addToBackStack針對的是具體的FragmentTransaction。既然addToBackStack針對的是FragmentTransaction,那么他的參數(shù)tag其實(shí)跟Fragment的tag是沒有任何關(guān)系的。所以我再次將addToBackStack("blank")改成addToBackStack("cccc")然后調(diào)用popBackStack()。發(fā)現(xiàn)結(jié)果依然是兩個(gè)fragment都消失了。從這就可以看出來addToBackStack是針對的具體的FragmentTransaction。

3.addToBackStack與replace
我們都知道addToBackStack會(huì)將FragmentTransaction加入回退棧中,此時(shí)當(dāng)前FragmentTransaction不再處于激活狀態(tài)時(shí),F(xiàn)ragment并不會(huì)被銷毀。當(dāng)我們想對同一容器疊加多個(gè)Fragment,實(shí)現(xiàn)動(dòng)態(tài)添加新Fragment同時(shí)還能back退回到前一個(gè)Fragment。這個(gè)addToBackStack添加的位置是有講究的。代碼如下:

protected void onCreate(Bundle savedInstanceState) {
      ...
      fragmentTransaction = fragmentManager.beginTransaction();
      fragmentTransaction.addToBackStack("cccc");
      fragmentTransaction.commit();
}

@OnClick({R.id.button1, R.id.button2})
protected void onClick(View v){
    switch (v.getId()){
       case R.id.button1:
          getSupportFragmentManager().popBackStack();
      ...
      case R.id.button2:
         ...
         FragmentTransaction f = getSupportFragmentManager().beginTransaction();
         f.replace(R.id.container, BlankFragment2.newInstance("第二層",""), "list");
//       f.addToBackStack("list");
         f.commit();
         ...
    }
...

這樣其實(shí)是不能實(shí)現(xiàn)該效果的。因?yàn)橹皇菍⒌谝粚拥腇ragmentTransaction管理的Fragment都加入了回退棧。同時(shí)因?yàn)檎{(diào)用replace,當(dāng)我們點(diǎn)擊button2,會(huì)看到第一層fragment不見了。這時(shí)候雖然fragmentTransaction管理的fragment沒有被銷毀但是視圖其實(shí)都已經(jīng)移除了。同時(shí)我們點(diǎn)擊button1他其實(shí)是將fragmentTransaction移除掉,而不是f。所以我們正確的實(shí)現(xiàn)是將f加到回退棧。

f.addToBackStack(null);

這樣后,會(huì)把第一層的fragment都去掉,然后添加第二層。點(diǎn)擊button1調(diào)用popBackStack后,第一層又會(huì)回來(replace相當(dāng)于remove和add的集合)。加入回退棧同時(shí)使用replace后,雖然第一層的實(shí)例沒有銷毀,但是視圖已經(jīng)是銷毀了。如果還想保存第一層的視圖,則把replace換成add。

如果對Fragment的一些基本概念還不是很了解,請看這篇文章 當(dāng)我們談Fragment時(shí),我們談些什么之一,這篇文章也不錯(cuò)Android -- Fragment 基本用法、生命周期與細(xì)節(jié)注意,也可以參考簡析 addToBackStack使用和Fragment執(zhí)行流程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容