当前位置: 首页 > 知识库问答 >
问题:

片段仍然添加到Backack而不调用addToBackStack,为什么?

杨腾
2023-03-14

我正在创建片段转换器助手类,对此我有一些问题。

我称之为碎片转换器

它有一个fragmentContainer,它是一个视图组,包含我想展示的所有片段。

我已经做了自己的替换(片段片段更改,布尔需要保存到堆栈)

功能是:

  • 从碎片容器中移除旧碎片

错误如下:

如果我使用我的替换功能并保存以使其正常工作,我可以使用设备的后退按钮后退并返回到先前添加的片段,它就像一个符咒。

但是,当我想替换一个片段而不保存到backStack时,我的代码中有一些错误,因为当我后退时,我可以在屏幕上看到我没有添加到backStack的片段,同时我还可以看到其他先前添加的片段!

所以我可以同时看到两个片段,就像这样:

这是我的代码:

//It is my helper class to handle replacing fragments.
public class FragmentChanger {

// fragmentTransaction
FragmentTransaction fragmentTransaction;

// the container for fragments
ViewGroup fragmentContainer;

// activity ofc
Activity act;

// Ctr: adding a default fragment to be the first so we can see it at app
// start
public FragmentChanger(Activity act, ViewGroup container, Fragment startingFragment) {

    this.act = act;
    this.fragmentContainer = container;
    fragmentTransaction = act.getFragmentManager().beginTransaction();
    fragmentTransaction.add(container.getId(), startingFragment, startingFragment.getClass().getSimpleName());
    fragmentTransaction.addToBackStack(startingFragment.getClass().getSimpleName());
    fragmentTransaction.commit();

}

// Replacing a fragment with an other one
public void replace(Fragment fragmentToChange, boolean needSaveToBackStack) {

    fragmentTransaction = act.getFragmentManager().beginTransaction();

    // replacing old fragment to the new one!
    fragmentTransaction.replace(fragmentContainer.getId(), fragmentToChange, fragmentToChange.getClass().getSimpleName());

    // Some null checking, and if the new fragment is NOT equals the current
    // fragment
    if (getCurrentFragment() != null && getCurrentFragment() != fragmentToChange) {

        /*** Important** because something here is wrong ***/

        // only addToBackStack when i want it, when needSaveToBackStack =
        // true!
        if (needSaveToBackStack) {
            fragmentTransaction.addToBackStack(fragmentToChange.getClass().getSimpleName());
        }
    }

    // commiting changes
    fragmentTransaction.commit();

}

// getting current Fragment
private Fragment getCurrentFragment() {

    try {

        FragmentManager fragmentManager = act.getFragmentManager();
        String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName();
        Fragment currentFragment = act.getFragmentManager().findFragmentByTag(fragmentTag);
        return currentFragment;

    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return null;
}

// Logging the back stack
public void logBackStack() {

    Log("Logging back stack:", "=============");

    FragmentManager fragmentManager = act.getFragmentManager();
    int stackSize = fragmentManager.getBackStackEntryCount();

    Log("Fragments count on the stack: ", stackSize + "");

    for (int i = 0; i < stackSize; i++) {
        String fragmentTag = fragmentManager.getBackStackEntryAt(i).getName();
        Log("Fragment on the stack: ", fragmentTag);
    }

}

private void Log(String str, String msg) {
    Log.i(str, msg);
}

}

这是我测试片段助手类的主要活动:

public class MainActivity extends Activity implements OnClickListener {

// My 3 Fragment Classes, could be N other type,
// in this example I only got 3
FragmentA fragmentA;
FragmentB fragmentB;
FragmentC fragmentC;

// Button to add the fragments manually
Button addA, addB, addC;

// This is my activity's container, its a simple viewGroup
// could be anything that can hold fragments
ViewGroup fragmentContainer;

// This is my fragment changer helper class that need some revision by you
// guys
FragmentChanger fragmentChanger;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //defining my adding buttons
    addA = (Button)findViewById(R.id.addAbtn);
    addB = (Button)findViewById(R.id.addBbtn);
    addC = (Button)findViewById(R.id.addCbtn);

    //setting onclicklistenrs
    addA.setOnClickListener(this);
    addB.setOnClickListener(this);
    addC.setOnClickListener(this);

    // defining my main container, this will holds fragments
    fragmentContainer = (ViewGroup) findViewById(R.id.fragmentContainer);

    // defining my fragments, each of them got an Activity (this), a
    // Container (mainContainer), and a Layout ofc.
    fragmentA = new FragmentA(this, fragmentContainer, R.layout.fragment_a_layout);
    fragmentB = new FragmentB(this, fragmentContainer, R.layout.fragment_b_layout);
    fragmentC = new FragmentC(this, fragmentContainer, R.layout.fragment_c_layout);

    // defining my fragment changer with an activity(this), a
    // container(mainContent) and a starting fragment to show!
    fragmentChanger = new FragmentChanger(this, fragmentContainer, fragmentA);

}

@Override
public void onClick(View view) {

    if (view.equals(addA)) {

        //When adding fragmentA, i always want to save it to backstack
        fragmentChanger.replace(fragmentA, true);

    } else if (view.equals(addB)) {

        //I dont want to save to back stack when adding B
        //So if i press back button, i dont want to see fragmentB ever again.
        //(But i do see, this is the error.)
        fragmentChanger.replace(fragmentB, false);
    } else if (view.equals(addC)) {

        //When adding fragmentC, i always want to save it to backstack
        fragmentChanger.replace(fragmentC, true);
    }

    //After any modification on fragments, i log the backstack
    fragmentChanger.logBackStack();

}

}

ps:我可以清楚地看到,如果我每次用我的帮助类替换片段时都记录堆栈,片段B永远不会在backStack上。那为什么如果我按下后退按钮会出现呢?

我非常感谢任何建议,这是我第一次尝试在我自己的helper类中使用片段,我希望它非常有用。

共有3个答案

欧阳安晏
2023-03-14

尝试使用FragmentTransacion替换片段。替换方法,如此处的链接所示

你也可以参考这个例子。这对我来说非常有效。

咸弘雅
2023-03-14

更改此行

    fragmentTransaction.add(container.getId(), startingFragment, startingFragment.getClass().getSimpleName());

    fragmentTransaction.replace(container.getId(), startingFragment, startingFragment.getClass().getSimpleName());
米楷
2023-03-14

所以在这里我发现你的代码有问题:

1) 您正在将片段和backbackbackentry的标记混合在一起。

String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName();

因此,在这里您将获得标记的BackStackEntry(不是片段),您添加或不添加在片段Transaction.addToBackStack()中。因此,您获得了错误的状态并将其用作当前片段。

2) 像在类字段中那样存储和重用片段通常不是一个好主意:FragmentA FragmentA 。它可能会导致国家和通货膨胀的问题,如果你不想解决额外的难题,最好在每笔交易中都创建它们。

 类似资料:
  • 我在Android中面临两个关于碎片的问题。 我有一个应用程序与一个导航抽屉片段在我的主要活动。当我在这个导航抽屉上单击一个项目时,一个新的片段会加载到主活动中的“fragment_placeholder”上。很简单。 创建MainActivity时,我将在fragment_placeholder中加载“homeFragment”。这个片段有一个带有两个标签的SlidingTabLayout,每个

  • 问题内容: 我知道十进制数不能用有限的二进制数精确地表示(解释),因此会失去一些精度,并且不会精确地表示。另一方面,因为是,所以可以精确表示。 话虽如此,将 三遍 相加并不完全是可以理解的,因此,以下代码将输出: 但是, 五次 相加会得到确切的结果呢?以下代码显示: 如果不能精确表示,将其相加5次给出的精确表示又如何呢? 问题答案: 舍入误差不是随机的,并且它的实现方式会尝试使误差最小化。这意味着

  • 隐藏程序是怎么处理碎片的?它只是将创建的视图设置为Gone吗?

  • 我知道十进制数不能精确地用有限二进制数表示(解释),因此将失去一些精度,并且不能精确地。另一方面,可以准确地表示,因为它是。 可以理解的是,三次添加并不能准确地给出,所以下面的代码打印: 如果不能精确地表示,那么添加5次它怎么能精确地给出可以精确地表示呢?

  • 问题内容: 在进行了-jvm-prevent-tail-call-optimizations之后的两年,似乎有一个原型 实现,并且MLVM一段时间以来将该功能列为“ proto 80%”。 Sun / Oracle方面对支持尾部调用是否没有积极的兴趣,还是就像JVM所提到的那样,尾部调用“ 注定要在每个功能优先级列表上排在第二位 ”?语言峰会? 如果有人测试了MLVM构建并可以分享一些关于其运行状

  • 你好, 我有MainActivity,TitlesFragment和DelessFragment。 我的MainActivity将显示TitlesFragment,当用户单击标题时,TitlesFragment将被DetailsFragment替换。那很好。然而,当我将DetailsFragment添加到addToBackStack时。当我点击后退按钮时,它会关闭应用程序,而不是显示标题碎片。 我