使用导航抽屉管理片段生命周期

3
我在我的应用程序中有一个架构问题。我使用了一个带有导航抽屉和多个片段的活动。现在,假设我有两个片段A和B。导航结构如下:
A
   A1
   A2

B

   B1
   B2

A1、A2是A fragment类型,B1、B2是B fragment类型。同一类型的fragment(如A1、A2)之间唯一的区别在于数据。

我的第一种方法:

当用户点击A1、A2、B1或B2时,我只需创建该类型的一个新实例并替换fragment即可。

  Fragment fragment =A.newInstance();

 private void replaceFragment(Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.content_frame, fragment).commit();
        mDrawerLayout.closeDrawer(rlDrawer);
    }

注意:我不想将它们添加到返回堆栈中。

后来我意识到这种方法是低效的,因为每次都会创建一个新的实例,即使它们是相同类型的。就像我之前说的,区别只在于数据。所以,我采用了下一种方法。

第二种方法:

现在我的活动拥有Fragment A和B的数据成员(引用)。现在我将检查它是否为空,如果为空则创建一个新实例,否则只需更改数据:

   if (A == null) {
            a = A.newInstance();
        } else {
            ((A) a).changeData();
        }
        replaceFragment(a);

这种方法的问题在于,当我从片段 A1 切换到 B1 时,A1 片段被销毁,但其引用仍留在活动中。现在,当我从 B1 切换回 A1 时,它不会创建一个新实例,如上面的代码所示,但同时 onCreate() 方法会在 Fragment A 上调用。

在 Fragment 的 onDestroy() 被调用时,我应该立即从活动中删除引用吗?

我的第二个方法正确吗?

有更好的方法吗?

先谢谢了。

1个回答

1
我会稍微修改你的第一种方法。 使用字符串标签来创建你的片段。 当你要替换一个片段时,使用三个参数的 replace 方法,例如:
  fragmentManager.beginTransaction()
                .replace(R.id.content_frame, fragment, TAG_A1).commit();

其中TAG_A1是唯一的字符串标记。

您可以使用findFragmentByTag方法从FragmentManager中查找片段是否已经被创建,然后再进行替换。

FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragmentA1 = fragmentManager.findFragmentByTag(TAG_A1);
if(fragment == null) {
    fragment = A.newInstance();
}
fragmentManager.beginTransaction()
                    .replace(R.id.content_frame, fragment, TAG_A1).commit();

我知道我们可以使用findByTag(),但我听说我们应该避免它,因为根据谷歌 I/O 中 Romain Guy 的讲话,它会影响性能。 - nitesh goel
我没有观看这个讲座,但我认为它比每次创建新片段要好。而且你并不经常调用它。 - LordRaydenMK
是的,确实比每次创建新片段要好,但是在我的第二种方法中,我并没有这样做。这就是为什么我问是否还有更好的方法来实现它。 - nitesh goel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接