Как работает цикл жизни страницы (Page Lifecycle)?
В Xamarin.Forms жизненный цикл страницы (Page Lifecycle) — это последовательность событий и методов, которые вызываются при создании, отображении, скрытии и уничтожении страницы (Page). Понимание этого цикла важно для правильной инициализации данных, освобождения ресурсов, обновления интерфейса и обработки навигации.
Страницы в Xamarin.Forms, такие как ContentPage, NavigationPage, TabbedPage, MasterDetailPage (или FlyoutPage) — являются основными строительными блоками пользовательского интерфейса. Каждая из них проходит через определённые стадии, начиная от создания и заканчивая уничтожением или повторной активацией.
Основные этапы жизненного цикла страницы
- **Создание экземпляра страницы (Constructor)
** - **OnAppearing() — страница отображается
** - **OnDisappearing() — страница скрывается
** - **Уничтожение (GC, если страница не используется)
**
Подробный разбор жизненного цикла
1. Конструктор (Constructor)
public MainPage()
{
InitializeComponent();
// Здесь создаются компоненты и инициализируются переменные
}
-
Вызывается при создании экземпляра страницы.
-
Выполняется один раз за "жизнь" страницы, если не используется повторная инициализация или кэширование.
-
Здесь можно задавать значения по умолчанию, подписываться на события, вызывать сервисы.
Важно: UI ещё не полностью сформирован, привязки могут быть неактивны.
2. OnAppearing()
protected override void OnAppearing()
{
base.OnAppearing();
// Код для загрузки данных, обновления интерфейса и подписки на события
}
-
Вызывается каждый раз, когда страница становится видимой для пользователя.
-
Отличается от конструктора тем, что может вызываться многократно, например, при возврате с другой страницы.
-
Используется для:
-
Загрузки/обновления данных
-
Обновления UI
-
Подписки на события
-
Запуска анимаций
-
Начала отслеживания GPS/датчиков
-
Пример: загрузить список сообщений при входе на страницу "Входящие".
3. OnDisappearing()
protected override void OnDisappearing()
{
base.OnDisappearing();
// Код для очистки ресурсов и отписки от событий
}
-
Вызывается каждый раз, когда страница перестаёт быть видимой.
-
Например:
-
При переходе на другую страницу
-
При сворачивании приложения (на некоторых платформах)
-
-
Используется для:
-
Сохранения состояния
-
Остановки таймеров
-
Отписки от событий
-
Освобождения ресурсов (например, подключения к БД)
-
Важно: OnDisappearing() не вызывается при закрытии приложения (если ОС не инициирует завершение корректно).
4. Уничтожение страницы (Garbage Collection)
-
Когда страница более не используется и на неё нет ссылок, сборщик мусора (GC) может освободить память.
-
Разработчику важно отписывать события и уничтожать ресурсы, чтобы предотвратить утечки памяти.
-
Специального метода OnDestroyed() не существует, но можно использовать IDisposable.
Пример:
public class MyPage : ContentPage, IDisposable
{
private bool disposed = false;
public void Dispose()
{
if (disposed) return;
// Очистка ресурсов
disposed = true;
}
}
Повторное использование страниц
Если используется Navigation.PushAsync(page), то каждый раз создаётся новая страница.
Если вы предварительно создали страницу один раз и повторно вызываете Navigation.PushAsync(savedPage), жизненный цикл будет отличаться:
-
Constructor вызывается один раз.
-
OnAppearing / OnDisappearing — каждый раз при отображении/скрытии.
Это позволяет сохранять состояние страницы между посещениями (например, вкладки в TabbedPage).
Жизненный цикл с навигацией
Действие | Страница A | Страница B |
---|---|---|
Создание A | Constructor, OnAppearing | — |
--- | --- | --- |
Переход на B (PushAsync) | OnDisappearing | Constructor, OnAppearing |
--- | --- | --- |
Возврат на A (PopAsync) | OnAppearing | OnDisappearing |
--- | --- | --- |
Асинхронная инициализация
Так как OnAppearing() — это void, нельзя напрямую использовать await. Чтобы загружать данные асинхронно, нужно вызывать асинхронные методы вручную:
protected override void OnAppearing()
{
base.OnAppearing();
_ = LoadDataAsync(); // "fire-and-forget"
}
private async Task LoadDataAsync()
{
IsBusy = true;
var data = await DataService.GetDataAsync();
Items = new ObservableCollection<Item>(data);
IsBusy = false;
}
Использование в MVVM
В MVVM логика жизненного цикла может быть реализована во ViewModel. Есть несколько способов:
1. Через событийную привязку в OnAppearing
protected override void OnAppearing()
{
base.OnAppearing();
(BindingContext as MyViewModel)?.OnPageAppearing();
}
2. Через интерфейс (например, IPageLifecycleAware)
Можно создать интерфейс:
public interface IPageLifecycleAware
{
void OnAppearing();
void OnDisappearing();
}
И реализовать его в ViewModel, вызывать вручную из Page.
Отличия на Android и iOS
-
В iOS и Android внутренние жизненные циклы (OnPause, OnResume, ViewWillAppear, и т.д.) обрабатываются Xamarin.Forms и транслируются в OnAppearing / OnDisappearing.
-
Поведение может различаться в зависимости от версии Xamarin.Forms, например:
-
В TabbedPage страницы могут не вызывать OnAppearing, если уже инициализированы.
-
В NavigationPage OnAppearing может вызываться при возврате, даже если страница не была удалена.
-
Расширенные события и трюки
Использование MessagingCenter
Если вы хотите получать уведомления о событиях вне самой страницы:
MessagingCenter.Send(this, "PageAppeared");
MessagingCenter.Subscribe<Page>(this, "PageAppeared", sender => {
// Обработка
});
Использование EventToCommand
В XAML можно подписать событие на команду ViewModel с помощью библиотек, таких как Prism или CommunityToolkit.
Сводка жизненного цикла
Стадия | Метод | Вызывается |
---|---|---|
Инициализация | Constructor | Один раз, при создании страницы |
--- | --- | --- |
Отображение | OnAppearing | Каждый раз при переходе на страницу |
--- | --- | --- |
Скрытие | OnDisappearing | При уходе со страницы |
--- | --- | --- |
Удаление | GC / Dispose | Если страница не используется |
--- | --- | --- |
Жизненный цикл страницы в Xamarin.Forms — это ключевой механизм управления ресурсами, состоянием и отображением данных. Правильное понимание порядка событий позволяет разработчику писать оптимальный и безопасный код, особенно в архитектуре MVVM и при работе с асинхронными источниками данных.