java - 处理 Android fragment 事务问题的正确/最佳方法

标签 java android android-fragments fragment

在我的开源 Android 应用程序中,发现了一个问题,即在特定情况下特定 fragment 会出现在另一个 fragment 之上或使应用程序崩溃。

GitHub上的问题如果你想看到更多的信息和示例截图: https://github.com/rpi-mobile/RPIMobile-Android/issues/31

我已经确定了原因,但想知道使用 android.support.v4.app 包中的哪些方法来解决问题。

MainActivity.java中,是使用FragmentTransaction.replace()切换fragments的抽屉导航代码。

出现这个问题是因为在 MapFragment 中,我使用:

ViewMapFragment vmf = new ViewMapFragment();
FragmentTransaction ft = getSherlockActivity().getSupportFragmentManager().beginTransaction();
ft.addToBackStack(null);
ft.replace(R.id.content_frame, vmf);
ft.commit();

ViewMapFragmentonDestroyView() 中:

FragmentManager fm = getSherlockActivity().getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.remove(fm.findFragmentById(R.id.mapview));
ft.commit();

onDestroyView() 正确地从 View 中删除了 ViewMapFragment,但是如果您在 View 中有它并使用抽屉导航更改为不同的 fragment , MapFragment 仍在返回堆栈中。

所以,对于我的问题:

1) 在尝试删除/替换特定 fragment 之前,我如何检查它是否在返回堆栈中,或者如果您在什么都没有时尝试(即不检查),应用程序不会崩溃吗?例如。当返回堆栈上没有任何内容时调用 popBackStack()

2) 我应该使用 FragmentManager 类方法尝试从后台堆栈中删除 MapFragment 还是应该使用 FragmentTransaction 方法?优缺点?

3) popBackStack()popBackStackImmediate() 在用户界面上有什么区别?用户是否看到一些故障转换?

最佳答案

根据 FragmentTransaction 的文档,当您调用 addToBackStack 方法时,它只会记住您在该事务中执行的操作。当调用 popBackStack 方法时,它将反转这些操作并执行它们。

那么,会发生什么:

  1. 当我们从 MapFragment 转到 ViewMapFragment 时,FragmentManager 会记得移除 MapFragment 并添加 ViewMapFragment 操作。
  2. 然后我们使用抽屉导航转到任何其他 fragment ,这会导致 ViewMapFragment 删除操作,然后添加从抽屉中选择的 fragment 。
  3. 最后,当我们按下后退按钮时,popBackStackImmediate 被调用并且 FragmentManager 执行相反的操作:ViewMapFragment 被移除(实际上它已经被移除)并添加 MapFragment。问题出现在这里 - 所选 fragment 仍然存在,因此我们同时在屏幕上显示了两个 fragment 。

有几种方法可以处理这种情况:

  1. 只需将 Navigation Drawer 操作添加到返回堆栈即可。
  2. 每次通过 Navigation Drawer 启动 fragment 切换时清除返回堆栈。

要清除返回堆栈,您可以使用此代码 (related question):

getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

如果将此行放在 selectItem 方法的开头,错误将得到修复。

还有你的问题:

  1. 您可以使用FragmentManager.findFragmentByTag 检查 fragment 是否在返回堆栈中。方法。请参阅我的回答末尾的示例。
  2. 从技术上讲,返回堆栈的一个条目可以包含多个 fragment ,我认为没有办法从中删除单个 fragment 。您可以清除返回堆栈而不是删除(请引用 question )。
  3. 主要区别在于,popBackStack 会在它实际开始弹出过程 (it will be started when application returns to it's event loop) 之前为您提供做某事的机会。

例子。例如,我们添加了一个带有标签“fragment-1”的 fragment :

getSupportFragmentManager()
        .beginTransaction()
        .replace(R.id.frame, new TestFragment(), "fragment-1")
        .commit();

然后,我们将它放入一个返回栈中,并用另一个 fragment 替换它:

getSupportFragmentManager()
        .beginTransaction()
        .addToBackStack(null)
        .replace(R.id.frame, new TestFragment(), "another-fragment")
        .commit();

此时 getSupportFragmentManager().findFragmentByTag("fragment-1") 返回我们的第一个 fragment (它从返回堆栈条目中获取)。现在我们可以通过 isAdded 检查这个 fragment 是否被添加到它的 Activity 中。方法 - 如果它返回 false,那么我们可以假设 fragment 在返回堆栈中。

关于java - 处理 Android fragment 事务问题的正确/最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25815621/

相关文章:

java - SDN4 : ClassCastException: java. util.HashMap 无法转换为 [EntityNode]

javascript - 在 Android 和 iPhone 的 JS 链接标签上触发点击事件

android - Viewpager 滑动不适用于回收站 View

java - Android 应用程序不执行按钮单击

java - 为什么Erlang中没有中间件?

java - 与 JSF 2.1 一起使用的 JSTL 版本

java - 新 fragment 在白色背景上过渡而不是旧 fragment

java - fragment 内旋转器基本适配器出现 NullPointerException 错误

Java - 通过类中的方法更改数组的值

java - libGDX - 如何在相机视口(viewport)中复制图 block 而不是按层复制?