Предпочтительно ли использовать 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
из активности хоста?
Ответы
Ответ 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