.NET MAUI - Managing The Application Lifecycle

The application lifecycle includes events such as startup, suspend, and resume. Every platform manages the application lifecycle differently, so implementing platform-specific code in iOS, Android, Tizen, Mac Catalyst and Windows projects would require some effort. However, .NET MAUI allows you to manage the app lifecycle in a unified way and takes care of performing the platform-specific work on your behalf. This article explains the app lifecycle and how you can manage your app’s behavior.

The App class

The App class is a singleton (single-instance) class that inherits from Application and that is defined inside the App.xaml.cs file. You can think of it as an object that represents your application running and includes the necessary infrastructure to handle resources, navigation, and the lifecycle. At a higher level, the App class exposes some fundamental members that you might need across the whole app lifecycle: the MainPage property you assign with the root page of your application, and methods you use to manage the application lifecycle that are described shortly.

Managing the app lifecycle

In .NET MAUI, the application lifecycle is handled by an object called Window. When the application starts up, an instance of this class is created. This instance also allows you to subscribe for events that represent moments of the lifecycle, and that are summarized as follows,

Event Description
Created Raised after the native window, or page for mobile apps. has been created. The cross-platform window will have a handler to the native one, but it might not be visible yet.
Activated Raised when the window (or page for mobile apps) has been activated and focused.
Deactivated Raised when the window, or page for mobile apps, has lost focus.
Stopped Raised when the window, or page for mobile apps, is no longer visible.
Resumed Raised when an app resumes after being stopped. This event can only be raised if the Stopped event was previously raised.
Destroying Raised when the native window (or page) is being destroyed and deallocated.

There are two ways for handling the app lifecycle events: overriding the CreateWindow method in the App class, and subclassing the Window class.

Overriding the CreateWindow method

The runtime invokes a method called CreateWindow to generate an instance of the Window class when the application starts up. You can override this method to subscribe for the app lifecycle events. The following code shows an example,

public partial class App: Application {
    public App() {
        InitializeComponent();
        MainPage = new AppShell();
    }
    protected override Window
    CreateWindow(IActivationState activationState) {
        Window window = base.CreateWindow(activationState);
        window.Created += (sender, eventArgs) => {
            // take actions here...
        };
        window.Activated += (sender, eventArgs) => {
            // take actions here...
        };
        return window;
    }
}

What you need to do is subscribe for one or more of the app events. As an example, the preceding code starts listening to the Created and Activated events. You will need to add your own logic to every event handler you subscribe, based on the type of event. For instance, if you were subscribing for the Destroying event, in the event handler you could write code that stores the state of the app and of its data.

Subclassing the Window class

An alternative to handling events in the App class directly is creating a class that derives from Window, and that overrides the methods that represent events. Due to .NET naming conventions, event names are preceded by the On prefix so you will have OnCreated, OnActivated, OnStopped etc. The following snippet shows an example about subclassing the Window class,

public class CustomWindow: Window {
    public CustomWindow(): base() {}
    public CustomWindow(Page page): base(page) {}
    protected override void OnCreated() {
        base.OnCreated();
    }
    protected override void OnActivated() {
        base.OnActivated();
    }
}

Add your own logic inside each event handler. At this point, the App class needs to create an instance of the Window object via the new CustomWindow class. This can be accomplished by overriding the CreateWindow method as follows,

protected override Window CreateWindow(IActivationState activationState) {
    CustomWindow window = (CustomWindow) base.CreateWindow(activationState);
    return window;
}

Handling native events and custom handlers

The events described in this section are common to all the supported platforms and can be handled in a cross-platform approach. Behind the scenes, they map native events that you can fully handle in the MauiProgram class. The following code shows how you can handle native events by invoking the ConfigureLifecycleEvents method, which requires a using Microsoft.Maui.LifecycleEvents; directive,

public static MauiApp CreateMauiApp() {
    var builder = MauiApp.CreateBuilder();
    builder.UseMauiApp < App > ().ConfigureFonts(fonts => {
        fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
        fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
    }).
    ConfigureLifecycleEvents(events => {
        #if ANDROID
        events.AddAndroid(android => android.OnBackPressed((activity) => {
            return false;
        }));
        #endif
    });
    return builder.Build();
}

Preprocessor directives give you the option to configure events only for the desired platform. The list of native events is extremely long for Android, iOS and Windows, so you are encouraged to walk through the documentation if you plan to have deeper control over lifecycle events. You will also find explanations about defining and registering custom events, which still happens via the ConfigureLifecycleEvents method.


Similar Articles