Перейти к содержимому

Практика 14. Практическая работа 14. Платформенные архитектуры и жизненный цикл (Android/iOS)

Раздел 2. Привязка к лекции 14. Работа аналитическая/проектная: разбираем нативные платформы, кода на React Native не пишем. Достаточно описаний, таблиц и псевдокода/последовательностей колбэков.

Цели работы

  • Разобраться в платформенных архитектурах мобильных приложений: MVVM, MVI, Clean — кто за что отвечает и как течёт данные.
  • Понять и описать жизненный цикл экрана на Android (Activity/Fragment) и iOS (UIViewController), сопоставить аналогичные колбэки.
  • Научиться рассуждать о сохранении состояния при повороте экрана, сворачивании и убийстве процесса на каждой платформе.
  • Уметь обоснованно выбирать архитектуру под конкретную фичу, а не «по привычке».

Задания

Задание 1. Сравнительная таблица: MVVM / MVI / Clean

Заполните таблицу и кратко прокомментируйте каждую строку своими словами (1–2 предложения).

КритерийMVVMMVIClean
Уровень примененияPresentation (экран)Presentation (экран)Всё приложение (слои)
УчастникиView, ViewModel, ModelView, Intent, Reducer, State, эффектыDomain (UseCase/Entity), Data, Presentation, Framework
СостояниеНесколько полей/потоков в VMОдно неизменяемое StateНе про состояние, а про границы слоёв
Поток данныхДвунаправленный: события ⇄ stateОднонаправленный: Intent → Reducer → StateЗависимости направлены внутрь (UI → Domain)
БойлерплейтНизкийВысокийСредний/высокий
Дебаг и трассировкаСреднийОтличный (лог интентов, time-travel)— (ортогонально)
ТестируемостьЛогика в VM/UseCaseЧистый reducer тестируется легкоDomain без зависимостей — юнит-тесты без устройства
ПлюсыПросто, ложится на Compose/SwiftUIПредсказуемость, единый источник правдыСлабая связность, замена SDK без переписывания домена
МинусыРиск «толстой» VMМного кода на простых экранахНакладные расходы на маленьких проектах
Когда выбиратьДефолт для большинства экрановСложные состояния, важны дебаг и предсказуемостьСредние/крупные долгоживущие проекты

Вывод для отчёта: объясните, почему подходы не взаимоисключающие (Clean задаёт слои, MVVM/MVI организуют экран) и приведите пример связки, например Clean + MVVM на уровне экрана.

Задание 2. Жизненный цикл экрана: Android vs iOS

2.1. Android. Опишите последовательность колбэков Activity и дополнительно отметьте специфику Fragment.

Activity: onCreate → onStart → onResume → [экран активен] → onPause → onStop → onDestroy
Fragment: onAttach → onCreate → onCreateView → onViewCreated → onStart → onResume
... onPause → onStop → onDestroyView → onDestroy → onDetach

Важно различать жизненный цикл фрагмента и его View: onCreateView/onDestroyView срабатывают чаще, View пересоздаётся, а сам фрагмент может жить дольше.

2.2. iOS. Опишите последовательность колбэков UIViewController.

UIViewController: viewDidLoad → viewWillAppear → viewDidAppear
... viewWillDisappear → viewDidDisappear

viewDidLoad вызывается один раз при создании View; viewWillAppear/viewDidAppearкаждый раз при показе экрана.

2.3. Заполните таблицу сопоставления аналогов.

НазначениеAndroidiOS
Разовая инициализация при создании ViewonCreate / onViewCreatedviewDidLoad
Экран вот-вот появитсяonStartviewWillAppear
Экран стал видимым/активнымonResumeviewDidAppear
Экран вот-вот скроетсяonPauseviewWillDisappear
Экран скрытonStopviewDidDisappear
Освобождение ресурсовonDestroy / onDestroyViewdeinit

В декларативных фреймворках вместо колбэков контроллера используют: Android Compose — эффекты + repeatOnLifecycle; SwiftUI — onAppear/onDisappear и @StateObject/@State, переживающие перерисовку.

Задание 3. Сценарий «поворот / сворачивание / убийство процесса»

Разберите три события и для каждого опишите, что произойдёт с состоянием и как его сохранить. Оформите как таблицу + короткий комментарий.

СобытиеAndroid: что происходитAndroid: как сохранитьiOS: что происходитiOS: как сохранить
Поворот экранаActivity/Fragment пересоздаётся, локальное состояние теряетсяViewModel переживает поворот; UI-состояние — в нейКонтроллер не пересоздаётся, меняются размеры (viewWillTransition)Состояние и так живёт в модели/VM, отдельных действий не требуется
Сворачивание (фон)onPause → onStop, объекты живы, но процесс может быть выгружен позжеТяжёлую работу остановить; данные — в VM/репозиторииviewWillDisappear, приложение в фоне (scenePhase/applicationDidEnterBackground)Сохранить незавершённый ввод в модель/хранилище
Убийство процессаВсё в памяти теряется, при возврате — новый процессSavedStateHandle (+ persistence: БД/файлы) для восстановленияСистему выгрузила приложение из памятиState Restoration (+ persistence) для восстановления экрана

Ключевая мысль для отчёта: долговечное состояние нельзя хранить в Activity/Fragment/UIViewController — его выносят в ViewModel/модель/сервис, а для переживания смерти процесса используют сериализуемое хранилище (SavedStateHandle / State Restoration / БД).

Дополнительно: объясните, почему сбор Flow/LiveData нужно делать lifecycle-aware (repeatOnLifecycle(STARTED)) — что произойдёт, если этого не сделать (утечки, фоновая работа).

Задание 4 (дополнительное). Выбор архитектуры под фичу

Выберите одну фичу из списка (или предложите свою) и обоснуйте архитектуру в 5–8 предложениях:

  1. Экран ленты новостей с пагинацией и pull-to-refresh.
  2. Сложная форма оформления заказа: 6 шагов, валидации, зависящие поля, отмена/возврат.
  3. Экран профиля «только чтение» с парой полей.
  4. Чат реального времени с историей сообщений и индикаторами доставки.

В обосновании укажите: выбранный подход (MVVM/MVI и нужен ли Clean), как организовано состояние, где живёт навигация, как переживается поворот/убийство процесса. Сошлитесь на критерии из Задания 1.

Ориентир: простой экран (п. 3) — MVVM без Clean; сложное состояние с откатами (п. 2, 4) — MVI и, при росте, Clean.


Критерии оценки

КритерийВес
Задание 1: таблица заполнена корректно, есть комментарии и вывод о сочетаемости подходов30%
Задание 2: последовательности колбэков верны, таблица аналогов сопоставлена правильно25%
Задание 3: разобраны все три события на обеих платформах, верно указаны механизмы сохранения25%
Задание 4 (доп.): обоснованный выбор со ссылкой на критерии10%
Аккуратность оформления, терминология, отсутствие путаницы Android/iOS10%

Итого: 100% (Задание 4 даёт до 10% и может компенсировать недочёты в основных).


Вопросы для самопроверки

  1. Чем MVVM отличается от MVI по управлению состоянием и потоку данных? Когда что выбирать?
  2. Почему Clean Architecture — это не альтернатива MVVM/MVI, а другой «срез» приложения?
  3. Чем отличается жизненный цикл фрагмента от жизненного цикла его View в Android?
  4. Какой колбэк iOS — аналог onResume, а какой — аналог onCreate? Почему viewDidLoad вызывается реже, чем viewWillAppear?
  5. Почему при повороте Android теряет состояние, а iOS — нет? Как это влияет на хранение данных?
  6. Как восстановить экран после убийства процесса в Android и в iOS соответственно?
  7. Зачем собирать Flow/LiveData через repeatOnLifecycle и что будет без этого?
  8. Где должна жить навигация и почему её не стоит держать во ViewModel?

Ресурсы

  • Лекция 14 «Платформенные архитектуры и жизненный цикл (Android/iOS)» — основной материал.
  • Android Developers: Guide to app architecture, Lifecycle, ViewModel, SavedStateHandle, Jetpack Navigation.
  • Apple Developer: View Controller Programming Guide, Managing Your App’s Life Cycle, State Restoration.
  • Jetpack Compose: side-effects, repeatOnLifecycle; SwiftUI: onAppear/onDisappear, @StateObject, scenePhase.
  • Материалы по MVI/Redux (связь с лекцией 11) и по Clean Architecture (правило зависимостей внутрь).