处理应用预启动

了解如何通过重写 OnLaunched 方法并调用 CoreApplication.EnablePrelaunch 来处理应用预启动。

简介

当允许使用可用的系统资源时,可通过在后台主动启动用户的最常用应用,提升桌面设备系列设备上的 UWP 应用的启动性能。 预启动的应用在启动后不久就会处于暂停状态。 然后,当用户调用应用时,应用会从暂停状态恢复为运行状态,这比冷启动应用要快。 用户的体验只是启动应用的速度非常快。

在Windows 10之前,应用不会自动利用预启动。 在 Windows 10 版本 1511 中,所有通用 Windows 平台 (UWP) 应用均已等待预启动。 在 Windows 10版本 1607 中,必须通过调用 CoreApplication.EnablePrelaunch 并传递 true来选择加入预启动行为。 此调用的一个好位置位于 OnLaunched 内,靠近发出检查的位置if (e.PrelaunchActivated == false)

是否预启动应用取决于系统资源。 如果系统遇到资源压力,则不会预启动应用。

某些类型的应用可能需要更改其启动行为,以便与预启动配合良好。 例如,启动时播放音乐的应用;一个游戏,假定用户存在,并在应用启动时显示复杂的视觉对象;消息应用可在启动期间更改用户的联机可见性-所有这些应用都可以识别预启动应用时间,并可以更改其启动行为,如以下各节所述。

XAML 项目的默认模板 (C#、VB、C++) 适应预启动。

预启动和应用生命周期

预启动应用后,它将进入暂停状态。 (请参阅处理应用暂停)。

检测和处理预启动

在激活期间,应用会收到 LaunchActivatedEventArgs.PrelaunchActivated 标志。 使用此标志运行应仅在用户显式启动应用(如以下显示的对 Application.OnLaunched 的修改)时运行的代码。

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
    // CoreApplication.EnablePrelaunch was introduced in Windows 10 version 1607
    bool canEnablePrelaunch = Windows.Foundation.Metadata.ApiInformation.IsMethodPresent("Windows.ApplicationModel.Core.CoreApplication", "EnablePrelaunch");

    // NOTE: Only enable this code if you are targeting a version of Windows 10 prior to version 1607,
    // and you want to opt out of prelaunch.
    // In Windows 10 version 1511, all UWP apps were candidates for prelaunch.
    // Starting in Windows 10 version 1607, the app must opt in to be prelaunched.
    //if ( !canEnablePrelaunch && e.PrelaunchActivated == true)
    //{
    //    return;
    //}

    Frame rootFrame = Window.Current.Content as Frame;

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (rootFrame == null)
    {
        // Create a Frame to act as the navigation context and navigate to the first page
        rootFrame = new Frame();

        rootFrame.NavigationFailed += OnNavigationFailed;

        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            //TODO: Load state from previously suspended application
        }

        // Place the frame in the current Window
        Window.Current.Content = rootFrame;
    }

    if (e.PrelaunchActivated == false)
    {
        // On Windows 10 version 1607 or later, this code signals that this app wants to participate in prelaunch
        if (canEnablePrelaunch)
        {
            TryEnablePrelaunch();
        }

        // TODO: This is not a prelaunch activation. Perform operations which
        // assume that the user explicitly launched the app such as updating
        // the online presence of the user on a social network, updating a
        // what's new feed, etc.

        if (rootFrame.Content == null)
        {
            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            rootFrame.Navigate(typeof(MainPage), e.Arguments);
        }
        // Ensure the current window is active
        Window.Current.Activate();
    }
}

/// <summary>
/// This method should be called only when the caller
/// determines that we're running on a system that
/// supports CoreApplication.EnablePrelaunch.
/// </summary>
private void TryEnablePrelaunch()
{
    Windows.ApplicationModel.Core.CoreApplication.EnablePrelaunch(true);
}

重要

上述代码示例中的 TryEnablePrelaunch 方法调用 CoreApplication.EnablePrelaunch。 仅当应用在支持 CoreApplication.EnablePrelaunch 的 Windows 版本上运行时,才会调用 TryEnablePrelaunch。 一般情况下,如果有疑问,则 只有在确定运行你的代码的平台支持 Windows API 后,才应使用该 API。 可以通过 ApiInformation 类执行此操作,如上面的代码示例所示。

上面的示例中还有一个代码,如果你的应用需要在 Windows 10 版本 1511 上运行时选择退出预启动,则可以取消注释。 在版本 1511 中,所有 UWP 应用都自动选择加入预启动,这可能不适合你的应用。

使用 VisibilityChanged 事件

用户看不到通过预启动激活的应用。 它们在用户切换到它们时可见。 你可能想要延迟某些操作,直到可以看到应用主窗口为止。 例如,如果你的应用显示来自某个源的新增项列表,你可以在 VisibilityChanged 事件期间更新该列表,而非使用在预启动该应用时生成的列表,因为该列表可能在用户激活该应用时就已过时。 以下代码处理 MainPageVisibilityChanged 事件:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        Window.Current.VisibilityChanged += WindowVisibilityChangedEventHandler;
    }

    void WindowVisibilityChangedEventHandler(System.Object sender, Windows.UI.Core.VisibilityChangedEventArgs e)
    {
        // Perform operations that should take place when the application becomes visible rather than
        // when it is prelaunched, such as building a what's new feed
    }
}

DirectX 游戏指南

DirectX 游戏通常不应启用预启动,因为许多 DirectX 游戏在可以检测到预启动之前执行其初始化。 从 Windows 1607 周年版本开始,默认情况下不会预启动你的游戏。 如果你希望你的游戏充分利用预启动,请调用 CoreApplication.EnablePrelaunch(true)

如果你的游戏面向早期版本的 Windows 10,你可以处理预启动条件退出应用程序:

void ViewProvider::OnActivated(CoreApplicationView const& /* appView */, Windows::ApplicationModel::Activation::IActivatedEventArgs const& args)
{
    if (args.Kind() == Windows::ApplicationModel::Activation::ActivationKind::Launch)
    {
        auto launchArgs{ args.as<Windows::ApplicationModel::Activation::LaunchActivatedEventArgs>()};
        if (launchArgs.PrelaunchActivated())
        {
            // Opt-out of Prelaunch.
            CoreApplication::Exit();
        }
    }
}

void ViewProvider::Initialize(CoreApplicationView const & appView)
{
    appView.Activated({ this, &App::OnActivated });
}
void ViewProvider::OnActivated(CoreApplicationView^ appView,IActivatedEventArgs^ args)
{
    if (args->Kind == ActivationKind::Launch)
    {
        auto launchArgs = static_cast<LaunchActivatedEventArgs^>(args);
        if (launchArgs->PrelaunchActivated)
        {
            // Opt-out of Prelaunch
            CoreApplication::Exit();
            return;
        }
    }
}

一般指南

  • 应用不应在预启动期间执行运行时间较长的操作,因为该应用会在无法快速暂停的情况下终止。
  • 预启动应用时,应用不应从 Application.OnLaunched 启动音频播放,因为该应用不可见并且音频播放的原因并不明显。
  • 假设应用对用户可见,或假设应用由用户显式启动,则应用不应在启动期间执行任何操作。 因为应用现在可以在后台启动并且无需用户显式操作,所以开发人员应该考虑隐私、用户体验和性能含义。
    • 一个隐私注意事项的示例是,社交应用应该何时将用户状态更改为在线。 它应该等到用户切换到该应用时才更改状态,而非在预启动应用时更改状态。
    • 一个用户体验注意事项的示例是,如果你拥有某个在启动时显示初级序列的应用(例如游戏),你可能会想要将该初级序列延迟到用户切换到该应用时。
    • 一个性能含义的示例是,你可能会等到用户切换到应用时才检索当前天气信息(而非在应用预启动时加载该信息),并且需要在应用可见时重新加载该信息,以确保该信息是最新的。
  • 如果你的应用在启动时清除动态磁贴,请将此操作延迟到执行可见性更改事件时。
  • 应用的遥测应可以区分正常磁贴激活和预启动激活,以便更轻松地缩小发生问题的方案。
  • 如果你有 Microsoft Visual Studio 2015 Update 1,并且Windows 10版本 1511,则可以通过选择“调试其他调试目标>调试> Windows 通用应用预启动”来模拟在 Visual Studio 2015 中应用应用的预启动