Хорошо, чтобы обновить фрагменты вместо создания новых экземпляров? - PullRequest
11 голосов
/ 30 января 2012

В примере об использовании фрагментов в документах Android, когда приложение находится в режиме «двойного просмотра», фрагмент сведений воссоздается всякий раз, когда приложению требуется показать подробности для другого заголовка. FragmentTransaction.replace() используется для замены каждого экземпляра старого фрагмента на новый.

Это рекомендуемая практика? Не расточительно ли создавать новый экземпляр пользовательского интерфейса, когда реальное намерение (без каламбура) - обновить то, что показывает пользовательский интерфейс, а не сам пользовательский интерфейс. Мне кажется, единственная причина для создания новых экземпляров состоит в том, если кто-то намеревается добавить их в backstack, чтобы пользователь мог повторить шаги. В противном случае безопасно / желательно обновить фрагмент напрямую?

В случае примера это будет означать метод, аналогичный DetailsFragment.setShownIndex(). Это будет вызвано, передавая новый индекс заголовка вместо воссоздания DetailsFragment.

Предположим, у нас есть версия примера, в которой одно действие управляет обоими фрагментами, но показывает только один, заменяя каждый фрагмент по мере необходимости. Хорошо ли, чтобы действие создавало экземпляр каждого фрагмента, сохраняло ссылки на каждый из них, а затем просто добавляло или удаляло эти два экземпляра из себя по мере необходимости?

Одним из возможных неприятных следствий этого будет то, что, когда фрагмент заголовков находится в состоянии resumed (т.е. на «переднем плане»), выбор заголовка приведет к вызову DetailsFragment.setShownIndex() в момент, когда детали фрагмент находится в stopped состоянии.

Хорошая идея? Плохая идея?

Заранее спасибо.

Ответы [ 2 ]

5 голосов
/ 31 января 2012

Как вы сказали, основной причиной создания новых экземпляров Fragment является простота использования заднего стека.Также вполне безопасно повторно использовать существующий фрагмент (ища его, используя FragmentManager.findFragmentById() или FragmentManager.findFragmentByTag()).Иногда вам нужно будет использовать методы Fragment, такие как isVisible(), isRemoving() и т. Д., Чтобы вы не могли незаконно ссылаться на компоненты пользовательского интерфейса, когда DetailsFragment равно stopped.

.В предлагаемом вами однопанельном действии с 2 фрагментами ваш метод setShownIndex может установить личное поле в DetailsFragment, которое загружается в onCreateView или onActivityCreated.

, например,

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 заново или используется повторно, onCreateView и onActivityCreated будут вызываться при добавлении DetailsFragment в контейнер.

Но если вам нужен обратный стек,Я настоятельно рекомендую просто создавать новые экземпляры, в противном случае вы просто реализуете свой собственный стек для содержимого DetailsFragment.

.
1 голос
/ 14 мая 2016

Я попробовал следующий код, и он работает для меня:

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;
}

Надеюсь, я смогу вам помочь

...