android - 防止后台堆栈中的相同片段
问题描述
我有一个活动。在这个活动中,有多个片段。片段按顺序添加,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()
}
解决方案
我不知道这是否完美,但曾经我做过这样的事情。我有一堆整数类型(我们称之为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
祝你好运。
推荐阅读
- workflow - Activiti 工作流重试机制是如何工作的
- java - JDK 13 预览功能:Textblock 为 equals 和 == 返回 false。制表符空间是否相关?
- mysql - Mysql Right join with mutiple condtion不起作用
- android - Android / iOS 应用内浏览器上的证书固定
- sql - 在 ODBC 中创建带有 blob 字段的表的 DDL 语法是什么?
- wpf - 如何在 WPF 项目中将 Quartz 配置保存到文件中?
- algorithm - 1. 请在 Codesignal.com 上解释这个解决方案 Rectangle Rotation 2. 请解释为什么我的解决方案不起作用
- python - 在 Django 中创建对象后重定向到 url 时出错
- c# - 如何使用 C# 从 OpenText ECM 页面下载文件
- c - 在 C 中使用 printf() 打印出这个字符符号 ÿ (ASCII 152)