fragments (lecture 09 – fragments)
TRANSCRIPT
FragmentsAndroid
Дмитрий Колесников
О чём речь?
Fragment представляет часть пользовательского интерфейса.Всегда привязан к Activity.Имеет собственный lifecycle, привязанный к Activity. ПодробнееПлюсы:
Позволяет реализовать гибкий интерфейс.Облегчает поддержку разных экранов.Декомпозиция и упрощение логики.
Пример использования.
Основные классы.
API 4+ via SupportLibrary
android.support.v4.app.FragmentActivityandroid.support.v7.app.ActionBarActivityandroid.support.v7.app.AppCompatActivityandroid.support.v4.app.Fragmentandroid.support.v4.app.FragmentManagerandroid.support.v4.app.FragmentTransaction
API 11+
android.app.Fragmentandroid.app.FragmentManagerandroid.app.FragmentTransaction
Жизненный цикл
Жизненный цикл
onAttach(Activity) Вызывается, когда фрагмент привязывается к Activity. С этого момента можноиспользовать getActivity()onCreate(Bundle) Вызывается, когда система создает фрагмент.onCreateView(LayoutIn�ater, ViewGroup, Bundle) Вызывается, когда фрагмент привязывается к иерархии View.onActivityCreated(Bundle) Вызывается, когда завершается onCreate() у Activity.onStart(); onResume(); onPause(); onStop() Аналогичные методы Activity.onDestroyView() Когда иерархия View разбирается.onDestroy() Вызывается, когда система разрушает фрагмент.onDetach() фрагмент больше не ассоциируется с Activity. С этого момента getActivity() возвращает null
Базовая реализация.
onCreate(Bundle) Инициализируем все ресурсы, связанные с фрагментом, кроме UI.onCreateView(LayoutIn�ater, ViewGroup, Bundle) Создаем и возвращаем View фрагмента.onViewCreated(View, Bundle) Инициализируем UI, устанавливаем adapter или другие данные.onResume() Инициализируем “дорогие” ресурсы: GPS, анимация, постоянное использование сети тд.onPause() Освобождаем “дорогие” ресурсы, сохраняем состояние.onDestroyView() Зануляем все ссылки на все View если мы их сохраняли.
Статичные фрагменты. 1 <?xml version="1.0" encoding="utf-8"?> 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent"> 5 6 <fragment class="com.example.android.apis.app.TitlesFragment" 7 android:id="@+id/titles" 8 android:layout_width="match_parent" 9 android:layout_height="match_parent" /> 10 11 </FrameLayout>
Нельзя убрать.Нельзя передавать аргументы.Обязательно должен быть задан id или tag.
Динамические фрагменты.
Добавляются в Runtime с помощью FragmentTransaction
1 FragmentTransaction transaction = getFragmentManager() 2 .beginTransaction(); 3 transaction.add(R.id.frame, new Fragment()); 4 transaction.commit();
getFragmentManager() (или getSupportFragmentManager() в случае использования Supportlibrary) Вызывается в Activity, возвращает FragmentManagerFragmentManager.beginTransaction() Создаем транзакцию.commit(), commitAllowingStateLoss() выполняем транзакцию.FragmentManager.executePendingTransactions() Убеждаемся что все транзакции завершены.
Состояние сохраняется.
Операции с фрагментами.
fragmentManager.�ndFragmentById(int)fragmentManager.�ndFragmentByTag(String)transaction.add(int, Fragment, String)transaction.remove(Fragment)transaction.replace(int, Fragment, String)transaction.hide(Fragment)transaction.show(Fragment)transaction.detach(Fragment) API 13transaction.attach(Fragment) API 13
С фрагментами задекларированными в layout почти ничего делать нельзя.
Backstack
FragmentTransaction.addToBackStack(String)FragmentManager.popBackStack()FragmentManager.getBackStackEntryCount()FragmentManager.getBackStackEntryAt(int) По возвращению из стека onCreateView(), onActivityCreated(), onStart(), and onResume()
Сохранение состояния
Нельзя хранить ссылки на элементы layout.Сохраняется в onSaveInstanceState(Bundle)Восстанавливается если savedState не null в onCreate(), onCreateView(), onViewCreated(), иonActivityCreated(). (с API 17 onViewStateRestored())Можно переиспользовать: setRetainInstance(true).
Activity - Fragment, Fragment - Fragment.
getFragmentManager().�ndFragmentById(int)getFragmentManager().�ndFragmentByTag(String)Fragment.getActivity()Interfaces.Fragment.setTargetFragment(Fragment, int), Fragment.getTargetFragment().Events: EventBus, Intents/LocalBroadcastReceiver
Наследники
DialogFragmentListFragmentPreferenceFragment нет в SupportLibraryWebViewFragment нет в SupportLibraryMapFragment из Google ServicesViewPager + FragmentPagerAdapter
Вложенные фрагменты API 17
Fragment.getChildFragmentManager()Fragment.getParentFragment()Состояние сохраняется.Жизненный цикл onCreateView() onDestroyView()Не умеет в Backstack.Нельзя использовать setRetainInstance(boolean)Проблемы с анимацией.Да и вообще не очень...
Подробнее
Делайте правильно, а не правильно - не делайте.
Хорошо:
newInstance(...)setArguments()Все диалоги – фрагментыХорошее разделение по смыслу: один фрагмент – одна задача.Сохранять состояние.Утилитные классы для избежания копипасты.
Делайте правильно, а не правильно - не делайте.
Плохо, иногда очень:
Отсутствие пустого конструктора.Забытые ссылки на элементы layout.Забытые вложенные анонимные классы, асинхронные задачи и тд.Вложенные фрагменты пересоздаются, даже если состояние родительскоговосстанавливается.
Ссылки
API GuidesGoogle Fragment TrainingFragmentFragmentTransactionFragmentManagerFragmentPagerAdapter