片段仍未调用addToBackStack而添加到Backstack,为什么? [英] Fragments still added to backstack without calling addToBackStack, why?

查看:57
本文介绍了片段仍未调用addToBackStack而添加到Backstack,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了片段转换助手类,但遇到了一些问题.

I making my fragment changer helper class and i have some issue with it.

我称之为 FragmentChanger

它有一个 fragmentContainer ,它是一个 ViewGroup ,其中包含我想显示的所有片段.

It has a fragmentContainer, which is a ViewGroup, that holds all the fragments i would like to show.

我已经制作了自己的 replace(fragmentFragmentToChange,boolean needSaveToBackStack)

功能是:

  • 从fragmentContainer中删除旧片段
  • 将新片段添加到fragmentContainer
  • (可选)保存到backStack,而 needSaveToBackStack true false .

错误是由于以下原因:

如果我将我的替换功能与保存到backStack一起使用是正常的,那么我可以使用设备的后退按钮来回移动并逐步添加到以前添加的片段,这就像一种魅力.

If i use my replace function with saving to backStack it is works properly, i can use my device's back button to stepping back and back to previsiously added fragments it is works like a charm.

但是,当我想替换而没有保存到backStack的片段时,我的代码出了点问题,因为当我退后一步时,我可以在屏幕上看到我所需要的片段没有添加到backStack ,并且我还可以同时看到另一个预先添加的片段!

But when i would like to replace a fragment withOUT saving to backStack, there is something wrong in my code because when i stepping back, i can see on the screen the fragment that i NOT added to the backStack, and ALSO i can see an other previsiously added fragment at the same time!

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

So i can see 2 fragments at the very same time, like this:

这是我的代码:

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

}

这是我的MainActivity,用于测试片段助手类:

And this is my MainActivity where i test my fragment helper class:

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:如果每次我用助手类替换Fragment时都记录堆栈,我可以清楚地看到fragmentB不在backStack上.然后,如果我按下后退按钮,为什么它会出现?

Ps: I can clearly see that fragmentB is never on the backStack if i logging the stack each time i replace a Fragment with my helper class. Then why is it appears if i push back button?

我非常感谢任何建议,这是我第一次尝试将片段与我自己的帮助器类一起使用,我想使其变得非常有用.

I greatly appreciate any advice, this is my first attempt with using fragments with my own helper class and i would like to make it greatly usable.

推荐答案

在这里,我发现您的代码有问题:

So here what I found wrong with your code:

1)您正在将 Fragment BackStackEntry 的标签混合在一起.

1) You are mixing together tags of Fragment and BackStackEntry.

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

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

So here you are getting the tag of BackStackEntry (not Fragment), which you adding or not in fragmentTransaction.addToBackStack(). Therefore, you are getting the wrong state and using it as current fragment.

2)像在类字段中那样存储和重用片段通常不是一个好主意: FragmentAfragmentA; .它可能导致状态和通货膨胀的问题,如果您不想解决其他难题,最好在每笔交易中都创建它们.

2) It is generally not a good idea to store and reuse fragments like you do in your class fields: FragmentA fragmentA;. It can lead to problems with state and inflation, it is better to create them on every transaction, if you don't want to solve additional puzzles.

这篇关于片段仍未调用addToBackStack而添加到Backstack,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆