【问题标题】:Prevent same fragments in backstack [duplicate]防止后台堆栈中的相同片段[重复]
【发布时间】:2020-02-27 17:42:07
【问题描述】:

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

现在,当我执行比顺序执行的操作时, D

但我必须像这样执行回栈, D

防止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()
        }

【问题讨论】:

标签: android android-fragments kotlin


【解决方案1】:

我不知道这是否完美,但我曾经做过这样的事情。我有一堆整数类型(我们称之为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),或者在我的示例中使用HashMap 而不是if-else 块。祝你好运。

【讨论】:

    【解决方案2】:

    在创建片段时为其设置一个标签,然后您可以通过片段管理器找到它并相应地替换/创建新的

    FragmentManager fManager = getFragmentManager();
    FragmentTransaction fTransaction = fManager.beginTransaction();
    Fragment fragment = fManager.findFragmentByTag("uniqueTag");
    
    // If fragment doesn't exist yet, create one
    if (fragment == null) {
         fTransaction.add(R.id.fragment_list, new ListFrag(), "uniqueTag");
     }else { // re-use the old fragment
         fTransaction.replace(R.id.fragment_list, fragment, "uniqueTag");
     }
    

    【讨论】:

      【解决方案3】:

      您可以使用dismiss() 就像您将A 转到B、B 到C 和C 到D 时一样,当您按下并解除从队列中删除的片段时,就像这样D 到C 和C 到B 和B to A 它让你的堆栈清晰并处理好文章

      【讨论】:

        猜你喜欢
        • 2017-05-08
        • 1970-01-01
        • 2022-12-11
        • 2012-06-22
        • 1970-01-01
        • 2011-09-24
        • 2021-04-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多