itmo_conspects

Лекция 2. Намерение, стек активностей, фрагмент

Намерение

Активности не вызывают друг друга непосредственно. Вместо этого одна активность выражает намерение создать (или сделать что-то другое) активность

Намерение выражается в объекте Intent - объекте для запроса действия от другого компонента Android, например, для создания службы Service

Есть три основных способа использования намерений:

К намерениям можно добавлять дополнительные данные с помощью метода putExtra

Также есть два типа намерений: явные и неявные

Само намерение состоит из:

Для того, чтобы иметь возможность принимать неявные намерения от операционной системы, нужно указать их типы в манифесте AndroidManifest.xml. Например, можно ограничиться намерениями, действия которых заключаются в просмотре веб-контента по https://my_host

<intent-filter>
   <action android:name="android.intent.action.VIEW" />
   <category android:name="android.intent.category.DEFAULT" />
   <category android:name="android.intent.category.BROWSABLE" />
   <data android:scheme="https" android:host="my_host" />
</intent-filter>

Такой блок называется фильтром намерений

Стек активностей

Одной из архитектурных целей, которые разработчики Android преследовали во время разработки, - это предсказуемость навигации. Для этого на нижней навигационной панели каждого приложения есть три универсальные кнопки: кнопка “Назад”, кнопка “Домой” и кнопка “Недавние” (в более поздних версиях есть возможность заменить эти кнопки на управление свайпами)

Кнопка “Назад” необходима для того, чтобы возвращаться на предыдущий экран с интерфейсом, а, чтобы иметь такую возможность, нужно хранить их

Для этого в каждом приложении есть стек активностей - Back Stack

Когда нажимается иконка приложения в телефоне, вызывается стартовая активность, которая кладется на вершину стека. Если из нее перейти в другую, то она положиться на вершину, тем самым по кнопке “Назад” можно возвращаться к предыдущим активностям

При повторном открытии приложения стек восстанавливается, при этом одна активность может существовать в стеке несколько раз

Правила дополнения стека и снятия со стека для конкретной активности можно переопределить с помощью свойства launchMode в манифесте AndroidManifest.xml:

Источник: https://developer.android.com/guide/components/activities/tasks-and-back-stack

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

Фрагмент

Фрагмент (Fragment, androidx.fragment.app.Fragment) - модульная часть интерфейса внутри активности. Фрагмент имеет свой жизненный цикл и может быть переиспользован в разных активностей. Также несколько фрагментов могут находиться в одной активности одновременно

Фрагменты преимущественно созданы для того, чтобы изменять разметку в зависимости о размеров экрана устройства

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

У фрагмента такой жизненный цикл:

Фрагмент создается как класс, наследующийся от Fragment:

class MyFragment : Fragment(R.layout.fragment_main)

Или вручную с созданием представления:

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
    _binding = FragmentMyBinding.inflate(inflater, container, false)
    return binding.root
}

В само приложение фрагмент добавляется:

Здесь создается транзакция, которая позволяет условно атомарно изменить фрагмент. Для навигации между фрагментами у FragmentTransaction есть три основных метода:

Другой метод, addToBackStack(), добавляет транзакцию в стек. При нажатии на кнопку “Назад” транзакция откатится и вернётся предыдущий фрагмент. Без этого нажатие кнопки “Назад” закроет активность

supportFragmentManager.beginTransaction()
    .replace(R.id.container, DetailFragment())
    .addToBackStack(null)
    .commit()

Для передачи данных между фрагментами можно использовать объект Bundle:

companion object {
    fun newInstance(name: String) = MyFragment().apply {
        arguments = Bundle().apply { putString("key", name) }
    }
}

Получить данные можно с помощью свойства arguments

val name = arguments?.getString("key")