К основному содержанию
скилл CX Codex

maui-app-lifecycle — скилл для Claude Code: жизненный цикл .NET MAUI

Подсказывает агенту, как правильно обрабатывать переходы состояний приложения .NET MAUI и сохранять данные при сворачивании.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add dotnet/skills --skill maui-app-lifecycle -a claude-code
Открыть на GitHub

Что делает maui-app-lifecycle

Скилл разбирает четыре состояния приложения .NET MAUI и шесть событий жизненного цикла окна: Created, Activated, Deactivated, Stopped, Resumed, Destroying. Агент получает готовые шаблоны подписки — через переопределение CreateWindow в классе App или через собственный подкласс Window с методами OnStopped, OnResumed, OnDestroying.

Отдельный блок — таблицы соответствия событий нативным колбэкам Android, iOS, Mac Catalyst и Windows. Тут есть подвох: у iOS имена селекторов UIKit и методов билдера AddiOS не совпадают, и методов .DidBecomeActive() или .WillResignActive() не существует. Нужны .OnActivated() и .OnResignActivation(), иначе код просто не соберётся. Это повод проверить, что агент не подставит привычные имена.

Для вызовов за пределами событий окна скилл показывает ConfigureLifecycleEvents в MauiProgram.cs с блоками #if ANDROID и другими директивами. Сохранение состояния строится на Preferences для мелких значений и сериализации в файл для крупного. Обработчики советует держать быстрыми, в пределах 1–2 секунд, и дублировать сохранение в OnDestroying на Android: кнопка «назад» может пропустить Stopped целиком.

Какие задачи решает

  • сохранить черновик текста при сворачивании приложения
  • восстановить позицию прокрутки после возврата в foreground
  • разобраться, чем Deactivated отличается от Stopped
  • подписаться на нативные колбэки Android и iOS через ConfigureLifecycleEvents
  • не потерять данные при выходе по кнопке «назад» на Android

Примеры запросов агенту

  • Покажи, как подписаться на события жизненного цикла окна в .NET MAUI и сохранить черновик в OnStopped
  • Сделай подкласс Window, который восстанавливает состояние в OnResumed
  • Как замапить события окна на колбэки iOS через AddiOS, чтобы код компилировался

Как установить maui-app-lifecycle

1Через Skills CLI (Vercel)

npx skills add dotnet/skills --skill maui-app-lifecycle -a claude-code

2Вручную: положить файлы

~/.claude/skills/maui-app-lifecycle/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/maui-app-lifecycle/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Из того же набора101

incremental-build Помогает выяснить, почему MSBuild пересобирает проект при отсутствии изменений в коде. Скилл анализирует binlog и находит сбои в Inputs и Outputs. CX Codex +1 3 400установок build-parallelism Разбирает, почему решение MSBuild собирается медленно: находит последовательную цепочку зависимостей и подсказывает, как её разорвать. CX Codex +1 3 400установок build-perf-baseline Скилл задаёт методику замера скорости сборки .NET и MSBuild перед оптимизацией. Он помогает зафиксировать холодный, тёплый и no-op прогоны с бинлогами. CX Codex +1 3 500установок thread-abort-migration Переводит устаревший вызов Thread.Abort из .NET Framework на кооперативную отмену задач через CancellationToken в .NET 6+. Помогает убрать ошибки PlatformNotSupportedException и предупреждения SYSLIB0006. CX Codex +1 3 300установок generate-testability-wrappers Скилл генерирует обёртки и регистрацию в DI для статических зависимостей C#, из-за которых код не получается покрыть тестами. CX Codex +1 3 300установок nuget-trusted-publishing Настраивает публикацию пакетов в nuget.org через GitHub Actions и OIDC без постоянных API-ключей. Пригодится при переводе сборки на NuGet/login или создании нового пайплайна. CX Codex +1 3 300установок resolve-project-references Помогает не оптимизировать ResolveProjectReferences по вводящей в заблуждение метрике MSBuild. Нужен при разборе медленной сборки с binlog. CX Codex +1 3 300установок migrate-dotnet8-to-dotnet9 Скилл ведёт проект с net8.0 на net9.0: правит TargetFramework, разбирает ошибки сборки и поведенческие изменения .NET 9, C# 13, ASP.NET Core 9 и EF Core 9. CX Codex +1 3 400установок

Похожие

dotnet-maui официальный github Правило задаёт Copilot стиль кода .NET MAUI: MVVM, CollectionView вместо ListView, Shell-навигация. Пригодится, если агент лезет в XAML и C#. ★ 40 418звёзд репо mvvm-toolkit-di официальный github Помогает связать ViewModels из CommunityToolkit.Mvvm с контейнером Microsoft.Extensions.DependencyInjection в проектах на WPF, WinUI 3, .NET MAUI, Uno и Avalonia. 92установок app-analytics appeeky Помогает настроить трекинг мобильного приложения, собрать карту событий и оценить воронку покупок. Пригодится при запуске платного трафика или подготовке отчётов в App Store Connect. CX Codex +1 3 400установок app-launch appeeky Скилл собирает план запуска мобильного приложения или крупного обновления: чек-лист по неделям, каналы продвижения и метрики. CX Codex +1 3 400установок build-zoom-meeting-sdk-app официальный anthropics Инструкции и шаблоны для интеграции Zoom Meeting SDK в веб и нативные клиенты. Помогает настроить JWT-подписи и устранить баги вёрстки. CX Codex +1 2 100установок app-ads kostja94 Скилл для планирования app install кампаний и user acquisition: подсказывает площадки, ставки и метрики, когда вы продвигаете мобильное приложение. CX Codex +1 1 100установок

Рядом в теме «Мобильная разработка»

Всё по теме «Мобильная разработка» →

Вопросы о maui-app-lifecycle

Как установить maui-app-lifecycle в Claude?

Выполните npx skills add dotnet/skills --skill maui-app-lifecycle -a claude-code. Файл скилла окажется по пути ~/.claude/skills/maui-app-lifecycle/SKILL.md.

Что делает maui-app-lifecycle?

Даёт агенту справочник по состояниям приложения .NET MAUI, событиям жизненного цикла окна и их нативным аналогам на Android, iOS, Mac Catalyst и Windows. Плюс шаблоны сохранения и восстановления состояния.

С какими другими скиллами он пересекается?

Навигацию по страницам ведёт maui-shell-navigation, регистрацию сервисов на старте — maui-dependency-injection. Вызовы платформенных API вне жизненного цикла скилл не покрывает.

Исходный текст

SKILL.md · MIT
---
name: maui-app-lifecycle
description: >-
  .NET MAUI app lifecycle guidance — the four app states, cross-platform Window
  lifecycle events (Created, Activated, Deactivated, Stopped, Resumed, Destroying),
  platform-specific lifecycle mapping, backgrounding and resume behavior, and
  state-preservation patterns.
  USE FOR: "app lifecycle", "window lifecycle events", "save state on background",
  "resume app", "OnStopped", "OnResumed", "backgrounding", "deactivated event",
  "ConfigureLifecycleEvents", "platform lifecycle hooks".
  DO NOT USE FOR: navigation events (use maui-shell-navigation),
  dependency injection setup (use maui-dependency-injection),
  platform API invocation (use conditional compilation and partial classes).
license: MIT
---

# .NET MAUI App Lifecycle

Handle application state transitions correctly in .NET MAUI. This skill covers the cross-platform Window lifecycle events, their platform-native mappings, and patterns for preserving state across backgrounding and resume cycles.

## When to Use

- Saving or restoring state when the app backgrounds or resumes
- Subscribing to Window lifecycle events (Created, Activated, Deactivated, Stopped, Resumed, Destroying)
- Hooking into platform-native lifecycle callbacks via `ConfigureLifecycleEvents`
- Deciding where to place initialization, teardown, or refresh logic
- Understanding the difference between Deactivated and Stopped

## When Not to Use

- Page-level navigation events — use Shell navigation guidance instead
- Registering services at startup — use dependency injection guidance instead
- Calling platform-specific APIs outside lifecycle context — use platform invoke guidance instead

## Inputs

- The target lifecycle transition (e.g., "save draft when backgrounded", "refresh data on resume")
- Which platforms the developer targets (Android, iOS, Mac Catalyst, Windows)
- Whether the app uses multiple windows (iPad, Mac Catalyst, desktop Windows)

## App States

A .NET MAUI app moves through four states:

| State | Description |
|---|---|
| **Not Running** | Process does not exist |
| **Running** | Foreground, receiving input |
| **Deactivated** | Visible but lost focus (dialog, split-screen, notification shade) |
| **Stopped** | Fully backgrounded, UI not visible |

Typical flow: Not Running → Running → Deactivated → Stopped → Running (resumed) or Not Running (terminated).

## Window Lifecycle Events

`Microsoft.Maui.Controls.Window` exposes six cross-platform events:

| Event | Fires when |
|---|---|
| `Created` | Native window allocated |
| `Activated` | Window receives input focus |
| `Deactivated` | Window loses focus (may still be visible) |
| `Stopped` | Window is no longer visible |
| `Resumed` | Window returns to foreground after Stopped |
| `Destroying` | Native window is being torn down |

### Subscribing via CreateWindow

Override `CreateWindow` in your `App` class and attach event handlers:

```csharp
public partial class App : Application
{
    protected override Window CreateWindow(IActivationState? activationState)
    {
        var window = base.CreateWindow(activationState);

        window.Created += (s, e) => Debug.WriteLine("Created");
        window.Activated += (s, e) => Debug.WriteLine("Activated");
        window.Deactivated += (s, e) => Debug.WriteLine("Deactivated");
        window.Stopped += (s, e) => Debug.WriteLine("Stopped");
        window.Resumed += (s, e) => Debug.WriteLine("Resumed");
        window.Destroying += (s, e) => Debug.WriteLine("Destroying");

        return window;
    }
}
```

### Subscribing via a Custom Window Subclass

Create a `Window` subclass and override the virtual methods:

```csharp
public class AppWindow : Window
{
    public AppWindow(Page page) : base(page) { }

    protected override void OnActivated() { /* refresh UI */ }
    protected override void OnStopped() { /* save state */ }
    protected override void OnResumed() { /* restore state */ }
    protected override void OnDestroying() { /* cleanup */ }
}
```

Return it from `CreateWindow`:

```csharp
protected override Window CreateWindow(IActivationState? activationState)
    => new AppWindow(new AppShell());
```

## Workflow: Save and Restore State on Background

1. **Identify transient state** — draft text, scroll position, form inputs, timer values.
2. **Save in `OnStopped`** — use `Preferences` for small values or file serialization for larger state.
3. **Restore in `OnResumed`** — read back saved values and apply to your view model.
4. **Also save in `OnDestroying`** on Android — the back button can skip `Stopped` entirely.
5. **Keep handlers fast** — complete within 1–2 seconds to avoid ANR on Android or watchdog kills on iOS.

```csharp
protected override void OnStopped()
{
    base.OnStopped();
    Preferences.Set("draft_text", _viewModel.DraftText);
    Preferences.Set("scroll_y", _viewModel.ScrollY);
}

protected override void OnResumed()
{
    base.OnResumed();
    _viewModel.DraftText = Preferences.Get("draft_text", string.Empty);
    _viewModel.ScrollY = Preferences.Get("scroll_y", 0.0);
}

protected override void OnDestroying()
{
    base.OnDestroying();
    // Android back-button can skip Stopped
    Preferences.Set("draft_text", _viewModel.DraftText);
}
```

## Platform Lifecycle Mapping

### Android

| Window Event | Android Callback |
|---|---|
| Created | `OnCreate` |
| Activated | `OnResume` |
| Deactivated | `OnPause` |
| Stopped | `OnStop` |
| Resumed | `OnRestart` → `OnStart` → `OnResume` |
| Destroying | `OnDestroy` |

### iOS / Mac Catalyst

| Window Event | UIKit Callback | `AddiOS` builder method |
|---|---|---|
| Created | `WillFinishLaunching` / `SceneWillConnect` | `.WillFinishLaunching()` / `.SceneWillConnect()` |
| Activated | `DidBecomeActive` | `.OnActivated()` |
| Deactivated | `WillResignActive` | `.OnResignActivation()` |
| Stopped | `DidEnterBackground` | `.DidEnterBackground()` |
| Resumed | `WillEnterForeground` | `.WillEnterForeground()` |
| Destroying | `WillTerminate` | `.WillTerminate()` |

> ⚠️ The UIKit selector names and the `AddiOS` builder method names differ for
> activation. There is **no** `.DidBecomeActive()` or `.WillResignActive()` builder
> method — use `.OnActivated()` and `.OnResignActivation()` or the code will not compile.

### Windows (WinUI)

| Window Event | WinUI Callback |
|---|---|
| Created | `OnLaunched` |
| Activated | `Activated` (foreground) |
| Deactivated | `Activated` (background) |
| Stopped | `VisibilityChanged` (false) |
| Resumed | `VisibilityChanged` (true) |
| Destroying | `Closed` |

## Hooking Native Lifecycle Directly

Use `ConfigureLifecycleEvents` in `MauiProgram.cs` when you need platform-specific callbacks beyond what Window events provide:

```csharp
builder.ConfigureLifecycleEvents(events =>
{
#if ANDROID
    events.AddAndroid(android => android
        .OnCreate((activity, bundle) => Debug.WriteLine("Android OnCreate"))
        .OnResume(activity => Debug.WriteLine("Android OnResume"))
        .OnPause(activity => Debug.WriteLine("Android OnPause"))
        .OnStop(activity => Debug.WriteLine("Android OnStop"))
        .OnDestroy(activity => Debug.WriteLine("Android OnDestroy")));
#elif IOS || MACCATALYST
    events.AddiOS(ios => ios
        .OnActivated(app => Debug.WriteLine("iOS OnActivated"))
        .OnResignActivation(app => Debug.WriteLine("iOS OnResignActivation"))
        .DidEnterBackground(app => Debug.WriteLine("iOS DidEnterBackground"))
        .WillEnterForeground(app => Debug.WriteLine("iOS WillEnterForeground")));
#elif WINDOWS
    events.AddWindows(windows => windows
        .OnLaunched((app, args) => Debug.WriteLine("Windows OnLaunched"))
        .OnActivated((window, args) => Debug.WriteLine("Windows Activated"))
        .OnClosed((window, args) => Debug.WriteLine("Windows Closed")));
#endif
});
```

## Common Pitfalls

1. **Resumed does not fire on first launch.** The initial sequence is `Created` → `Activated`. Use `OnActivated` for logic that must run on every foreground entry, not `OnResumed`.

2. **Deactivated ≠ Stopped.** A dialog, split-screen, or notification pull-down triggers `Deactivated` without `Stopped`. Do not perform heavy saves in `OnDeactivated` — the app may never actually background.

3. **Android back button skips Stopped.** On Android, pressing back may call `Destroying` directly without `Stopped`. Place critical save logic in both `OnStopped` and `OnDestroying`.

4. **Multi-window apps fire events independently.** On iPad, Mac Catalyst, and desktop Windows each `Window` instance fires its own lifecycle events. Do not assume a single global lifecycle.

5. **Long-running handlers cause kills.** Android enforces a ~5 second ANR timeout; iOS has limited background execution time. Keep lifecycle handlers synchronous and fast — use `Preferences` for quick saves, not database writes.

6. **Do not use legacy Xamarin.Forms lifecycle methods.** `Application.OnStart()`, `Application.OnSleep()`, and `Application.OnResume()` exist for backward compatibility but bypass Window-level events. In .NET MAUI, prefer `Window` lifecycle events (`OnActivated`, `OnStopped`, `OnResumed`, etc.) for correct multi-window behavior.

© dotnet · MIT · dotnet/skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой