处理应用程序预启动

了解如何通过重写 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 后,才应使用 Windows 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,那么可以在 Visual Studio 2015 中选择 调试>其他调试目标>调试 Windows 通用应用预启动,来模拟您的应用的预启动。