Подтвердить что ты не робот

Предпочтительно ли использовать 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);
    }
  }
  ...
}

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

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

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

4b9b3361

Ответ 1

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

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

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

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

LocalBroadcastManager

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

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

Ответ 2

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

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

Чтобы воспользоваться преимуществами 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