好的是更新片段而不是创建新实例?

时间:2012-01-30 09:25:20

标签: android android-activity transactions lifecycle fragment

在使用Android文档中的片段的example中,当应用程序处于“双视图”模式时,只要应用程序需要显示不同标题的详细信息,就会重新创建详细信息片段。 FragmentTransaction.replace()用于将每个旧的详细信息片段实例换成​​新的。

这是推荐的做法吗?当真正的意图(没有双关语意图)要更新UI显示的内容而不是UI本身时,创建新的UI实例并不浪费。在我看来,创建新实例的唯一原因是,如果有人打算将它们添加到backstack,那么用户可以回溯步骤。否则,直接更新片段是否安全/可取?

在该示例的情况下,它将意味着沿DetailsFragment.setShownIndex()行的方法。这将被调用,传入新的标题索引,而不是重新创建DetailsFragment

假设我们有一个示例版本,其中一个活动管理两个片段,但一次只显示一个片段,根据需要交换每个片段。活动是否可以创建每个片段的实例,保留对每个片段的引用,然后根据需要简单地添加或删除这两个实例?

这可能是一个棘手的后果,当标题片段处于resumed状态时(即在'前景'中),选择标题将导致调用DetailsFragment.setShownIndex()细节片段处于stopped状态的时间。

好主意?不好主意?

提前致谢。

2 个答案:

答案 0 :(得分:5)

就像你说的,创建新Fragment实例的主要原因是为了便于使用后端堆栈。重用现有的片段(使用FragmentManager.findFragmentById()FragmentManager.findFragmentByTag()查找)也非常安全。有时您需要充分利用isVisible()isRemoving()等片段方法,以便在DetailsFragmentstopped时不会非法引用UI组件。

无论如何,在您建议的包含2个片段的单一窗格活动中,您的setShownIndex方法可以在DetailsFragment中设置一个加载在onCreateViewonActivityCreated中的私有字段。< / p>

如,

DetailsFragment df = getFragmentManager().findFragmentByTag("details");
if (df != null) {
    df.setShownIndex(getSelectedIndex());
} else {
    df = DetailsFragment.newInstance(getSelectedIndex());
}
fragmentTransaction.replace(R.id.frame, df, "details").commit();

在这两种情况下,无论是新创建还是重复使用df,onCreateViewonActivityCreated都会在DetailsFragment添加到容器时调用。

但是如果你想要一个后台堆栈,我强烈建议你只创建新实例,否则你只是为DetailsFragment的内容实现自己的后台堆栈。

答案 1 :(得分:1)

我尝试了以下代码,它适用于我:

private void replaceFragment(Class fragmentClass, String FRAGMENT_NAME, android.support.v4.app.FragmentManager fragmentManager) {

    Fragment fragment = null;
    String backStateName = fragmentClass.getName(); // nome della classe del Fragment

    Log.d("Fragment: ", "Creazione Fragment: "+backStateName);


    Boolean fragmentExit = isFragmentInBackstack(fragmentManager, backStateName);


    if (fragmentExit) { //Il Fragment è presente nello stacback

        // Fragment exists, go back to that fragment
        //// you can also use POP_BACK_STACK_INCLUSIVE flag, depending on flow
        fragmentManager.popBackStackImmediate(fragmentClass.getName(), 0);

    } else {

        // se non esiste lo aggiungiamo
        try {
            fragment = (Fragment) fragmentClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Inizializzo la transazione del Fragment
        android.support.v4.app.FragmentTransaction ft = fragmentManager.beginTransaction();
        ft.setCustomAnimations(
                R.anim.fragment_slide_left_enter,
                R.anim.fragment_slide_left_exit,
                R.anim.fragment_slide_right_enter,
                R.anim.fragment_slide_right_exit);
        ft.replace(R.id.frameLayout_contentMain, fragment, FRAGMENT_NAME);
        ft.addToBackStack(fragmentClass.getName());
        ft.commit();

        // Recupero il numero di Fragment presenti
        Integer nFragment = fragmentManager.getBackStackEntryCount();

        Log.d("Fragment: ", "Numero di Fragment: "+nFragment);

    }

}

要确定片段是否已经在StackBack中,请执行此函数:

public static boolean isFragmentInBackstack(final android.support.v4.app.FragmentManager fragmentManager, final String fragmentTagName) {
    for (int entry = 0; entry < fragmentManager.getBackStackEntryCount(); entry++) {
        if (fragmentTagName.equals(fragmentManager.getBackStackEntryAt(entry).getName())) {
            return true;
        }
    }
    return false;
}

我希望我能帮到你