首页 > 解决方案 > 防止后台堆栈中的相同片段

问题描述

我有一个活动。在这个活动中,有多个片段。片段按顺序添加,A -> B -> C -> D -> B -> C -> D

现在,当我执行比顺序执行的操作时,D <- C <- B <- D <- C <- B <- A

但我必须像这样执行回栈,D <- C <- B <- A

防止 backStack 中出现相同 Fragment 的正确方法是什么?

这是我添加片段的代码,

 if (fragment != null) {
            val transaction = fragmentManager.beginTransaction()
            if (bundle != null)
                fragment.arguments = bundle
                transaction.add(R.id.container_body, fragment)
                transaction.addToBackStack(fragTag)
                // Commit the transaction
                transaction.commit()
        }

并且对于 backstack 执行,

 if (supportFragmentManager.backStackEntryCount > 0) {
            supportFragmentManager.popBackStackImmediate()
        }

标签: androidandroid-fragmentskotlin

解决方案


我不知道这是否完美,但曾经我做过这样的事情。我有一堆整数类型(我们称之为stackOfFragmentTracker)。所以假设你有片段 f1、f2、f3、f4,你做了 f1->f3->f4->f2。然后stackOfFragmentTracker会有这样的内容:1->3->4->2。

接下来,您只为每个片段创建一个实例(因此在我的示例中,例如 f1、f2、f3、f4 各只有一个实例),并且您将它们以 INVISIBLE 状态保存在 backStack 中:

final int ONE = 1; // a map to Fragment 1
final int TWO = 2; // a map to fragment 2

stackOfFragmentTracker.push(ONE);
ExampleFragment f1 = null;
        if(fragmentManager.findFragmentByTag(ExampleFragment.TAG)==null){
            f1 = new ExampleFragment();
            fragmentManager.beginTransaction()
                    .add(R.id.flToMountOn, f1, ExampleFragment.TAG)
                    .addToBackStack(ExampleFragment.TAG)
                    .hide(f1)  // <------- this makes your fragment invisible
                    .commit();
        }

你会为你所有的片段这样做。

接下来,您需要一个 Fragment 变量(例如Fragment active),将其指向您的第一个片段(即您第一次想去的地方)并使其可见。

active = f1;
fragmentManager.beginTransaction().show(f1).commit();

为了保持清洁,您可以使用以下两种方法:

    private void hideActiveFragment(){
        if(currentlyActiveFragment!=null){
            fragmentManager.beginTransaction().hide(currentlyActiveFragment).commit();
        }
    }

    private void showActiveFragment(Fragment nextFragment){
        active = nextFragment;
        if(active!=null){
            fragmentManager.beginTransaction().show(active).commit();
        }
    }

最后,每当您前进时,您将输入一个数字stackOfFragmentTracker并简单地使该片段可见:

// say we are going to f2

void switchFragment(int n){
  stackOfFragmentTracker.push(n); // you may keep a check if n is valid or not
  if(n==1){
    hideActiveFragment();
    showActiveFragment(f1);
  }else if(n==2){
    hideActiveFragment();
    showActiveFragment(f2);
  } // ... ... ...
}

onBackPress这样做:

void insideBackPress(){
  stackOfFragmentTracker.pop();
  int top = stackOfFragmentTracker.top();
 if(top==1){
    hideActiveFragment();
    showActiveFragment(f1);
  }else if(top==2){
    hideActiveFragment();
    showActiveFragment(f2);
  } // ... ... ...
}

我知道这个例子有点混乱,但我希望你明白这一点。为各种极端情况添加必要的检查(如果 stackOfFragmentTracker isEmpty),或者在我的示例中使用 aHashMap而不是块。if-else祝你好运。


推荐阅读