Желательно ли использовать Activity.onAttachFragment или Fragment.onAttach для связи между Activity и вложенным фрагментом?

Документация Android предполагает, что для связи с активностью с размещенным фрагментом фрагмент может определять интерфейс обратного вызова и требовать, чтобы его активность выполняла его. Основной шаблон включает в себя реализацию onAttach в вашем фрагменте и включение активности в обратную связь. См. Http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity .

Ниже приведен пример предоставления фрагмента некоторым данным инициализации, а также прослушивание обратного вызова навигации.

 public class HostActivity extends Activity implements FragmentHost { @Override UiModel getUiModel() { return mUiModel; } @Override FragmentNavListener getNavListener() { return mNavListener; } ... } public class HostedFragment extends Fragment { @Override public void onAttach(Activity activity) { super.onAttach(activity); if (activity instanceof FragmentHost) { FragmentHost host = (FragmentHost) activity; setUiModel(host.getUiModel()); setNavListener(host.getFragmentNavListener()); } } ... } 

Сравните это с использованием onAttachFragment в активности хоста, чтобы явно инициализировать фрагмент:

 public class HostActivity extends Activity { @Override public void onAttachFragment(Fragment fragment) { super.onAttachFragment(fragment); if (fragment instanceof HostedFragment) { HostedFragment hostedFragment = ((HostFragment) fragment); hostedFragment.setUiModel(mUiModel); hostedFragment.setNavListener(mNavListener); } } ... } 

Для меня кажется, что у первого шаблона есть некоторые недостатки:

  1. Это делает фрагмент труднее использовать из разных действий, поскольку, поскольку все эти действия должны реализовать требуемый интерфейс. Я могу представить случаи, когда конкретный экземпляр фрагмента не требует полной настройки хост-активности, но для всех потенциальных действий хоста потребуется реализовать интерфейс хоста.
  2. Это делает код немного сложнее для кого-то, незнакомого с используемым шаблоном. Инициализация фрагмента в onFragmentAttached выглядит проще, поскольку код инициализации живет в том же классе, который создает фрагмент.
  3. Модульное тестирование с использованием библиотеки Robolectric становится сложнее, так как при вызове onAttach вы должны теперь реализовать FragmentHost, а не просто вызвать onAttach (new Activity ().

Для тех из вас, кто сделал деятельность по фрагментации общения, какой шаблон вы считаете предпочтительным и почему? Есть ли недостатки в использовании onAttachFragment из активности хоста?

Solutions Collecting From Web of "Желательно ли использовать Activity.onAttachFragment или Fragment.onAttach для связи между Activity и вложенным фрагментом?"

Я не могу говорить лично в отношении тестирования, но есть альтернативы обмену интерфейсом обратного вызова фрагмента / активности.

Например, вы можете использовать шину событий для развязки фрагментов и вашей активности. Здесь можно найти отличный автобус:

Отто – событие Автобус по площади

Он активно разрабатывается некоторыми очень талантливыми инженерами на площади. Вы также можете использовать LocalBroadcastManager, который упакован в библиотеку поддержки Android.

LocalBroadcastManager

У Эрика Берка с площади есть презентация, где он упоминает обоим, которые можно найти здесь:

Android-приложение «Анатомия»

Я использовал шаблон Fragment.onAttach(...) в своем последнем проекте. Я вижу два преимущества:

  1. Вы можете проверить на раннем этапе, что хостинг-деятельность реализует необходимый интерфейс и генерирует исключение, если нет
  2. Существует меньше риска удержания ссылки на контекст хостинга после того, как фрагмент был отсоединен

Чтобы воспользоваться преимуществами 2., вы не должны хранить ссылки на UiModel и NavListener , как и в своем примере кода. Вместо этого, когда вы хотите взаимодействовать с этими экземплярами, вы должны использовать код ((FragmentHost) getActivity).getNavListener().onNav(this) или, альтернативно ((FragmentHost) getActivity).onNav(this) . Вы можете сохранить хост фрагмента в поле, в котором вы устанавливаете значение null в onDetach(...) в качестве подхода средней точки, если вы хотите избежать постоянной кастинга.

Я согласен, что инициализация фрагмента из создаваемой им деятельности кажется более интуитивной.

Сказав все это, я собираюсь вообще пропустить фрагменты в моем текущем проекте. Следующая статья отражает уроки, извлеченные из моей последней довольно хорошо: https://corner.squareup.com/2014/10/advocating-against-android-fragments.html