onResume 调用了 "dead" 个片段 - 如何正确恢复?
onResume called on "dead" fragments - how to recover correctly?
我使用支持库中的片段开发了一个应用程序。我只用了一个Activity。
该布局由一个带有折叠工具栏布局的协调器布局和一个导航视图组成。
选择导航项时,我在 NavigationItemSelectedListener 中执行以下操作:
switch (item.getItemId()) {
default:
return false;
case R.id.mainmenu_start:
navi.clear();
navi.navigate(new StartFragment(), R.id.fragment_container);
return true;
// ... More menu entries
}
So when selecting a new Item I clear the backstack (navi.clear()
) and replace the displayed fragment with a new one.
我遇到的问题是:"old"(已替换)片段不会被删除/分离。
因此,当我导航到 StartFragment,然后导航到另一个片段,然后再次选择 StartFragment 时,onResume
被调用两次:
一次在 "old" / 第一个 StartFragment 上,一次在新创建的 StartFragment 上。
如何避免这种行为?我要么想重用现有的片段(第一个),要么 创建一个新片段 - 但同时使用这两种片段会导致大量问题...
为了研究这种行为,我给每个片段一个唯一的(递增的)ID:导航到新片段时,onResume 会在几个较旧的片段上调用,但不会在所有片段上调用。
例如:我总是选择相同的菜单条目进行导航。这是发生的"events",其中数字表示片段ID(所有片段都相同class(StartFragment)):
- 创建 1 个,恢复 1 个
- 创建 2,恢复 1,恢复 2
- 创建 3,恢复 1,恢复 3
- 创建 4,恢复 2,恢复 3,恢复 4
所以有时候 "old" 片段会丢失,稍后再回来。有时也会在完全不同的片段上调用 onResume。 (所以我之前打开Fragment 2的时候,在新建Fragment 1的时候也会调用Fragment 2的onResume...)
完整性
导航功能:
public void clear() {
FragmentManager fragmentManager = ((MainActivity)context).getSupportFragmentManager();
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
public void navigate(Fragment fragment, int container, HashMap<String, Pair<String, View>> sharedElements) {
this.hideKeyboard();
FragmentTransaction ft = ((MainActivity)context).getSupportFragmentManager().beginTransaction();
ft.replace(container, fragment);
ft.addToBackStack(null);
ft.commit();
((MainActivity)context).getDrawerLayout().closeDrawers();
}
作为答案发布以备将来参考。
我认为您的问题是 popBackStack() 不会立即生效,而是计划在下一次事件循环传递时 运行 生效,这在您的情况下为时已晚并且会产生不良影响。应该帮助的是强制片段管理器事务立即完成。
可以通过调用 executePendingTransactions() or in this particular case by popBackStackImmediate()
来实现
我使用支持库中的片段开发了一个应用程序。我只用了一个Activity。 该布局由一个带有折叠工具栏布局的协调器布局和一个导航视图组成。 选择导航项时,我在 NavigationItemSelectedListener 中执行以下操作:
switch (item.getItemId()) {
default:
return false;
case R.id.mainmenu_start:
navi.clear();
navi.navigate(new StartFragment(), R.id.fragment_container);
return true;
// ... More menu entries
}
So when selecting a new Item I clear the backstack (navi.clear()
) and replace the displayed fragment with a new one.
我遇到的问题是:"old"(已替换)片段不会被删除/分离。
因此,当我导航到 StartFragment,然后导航到另一个片段,然后再次选择 StartFragment 时,onResume
被调用两次:
一次在 "old" / 第一个 StartFragment 上,一次在新创建的 StartFragment 上。
如何避免这种行为?我要么想重用现有的片段(第一个),要么 创建一个新片段 - 但同时使用这两种片段会导致大量问题...
为了研究这种行为,我给每个片段一个唯一的(递增的)ID:导航到新片段时,onResume 会在几个较旧的片段上调用,但不会在所有片段上调用。
例如:我总是选择相同的菜单条目进行导航。这是发生的"events",其中数字表示片段ID(所有片段都相同class(StartFragment)):
- 创建 1 个,恢复 1 个
- 创建 2,恢复 1,恢复 2
- 创建 3,恢复 1,恢复 3
- 创建 4,恢复 2,恢复 3,恢复 4
所以有时候 "old" 片段会丢失,稍后再回来。有时也会在完全不同的片段上调用 onResume。 (所以我之前打开Fragment 2的时候,在新建Fragment 1的时候也会调用Fragment 2的onResume...)
完整性
导航功能:
public void clear() {
FragmentManager fragmentManager = ((MainActivity)context).getSupportFragmentManager();
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
public void navigate(Fragment fragment, int container, HashMap<String, Pair<String, View>> sharedElements) {
this.hideKeyboard();
FragmentTransaction ft = ((MainActivity)context).getSupportFragmentManager().beginTransaction();
ft.replace(container, fragment);
ft.addToBackStack(null);
ft.commit();
((MainActivity)context).getDrawerLayout().closeDrawers();
}
作为答案发布以备将来参考。
我认为您的问题是 popBackStack() 不会立即生效,而是计划在下一次事件循环传递时 运行 生效,这在您的情况下为时已晚并且会产生不良影响。应该帮助的是强制片段管理器事务立即完成。
可以通过调用 executePendingTransactions() or in this particular case by popBackStackImmediate()
来实现