2. 应用程序的生命周期

Windows 8为应用程序引入了一个新的生命周期,完全不同于传统的桌面应用程序的生命周期。在Windows 8.1中有些变化,在Windows 10中又有一些变化。如果使用Windows 10和平板电脑模式,应用程序的生命周期与桌面模式是不同的。在平板电脑模式中,应用程序通常全屏显示。分离键盘(对于平板电脑设备,如Microsoft Surface),或在Action Center中使用Tablet Mode按钮,可以自动切换到平板模式。在平板模式下运行应用程序时,如果应用程序进入后台(用户切换到另一个应用程序),就会暂停,它不会得到任何更多的CPU利用率。这样,应用程序不消耗任何电力。应用程序在后台时,只使用内存,一旦用户切换到这个应用程序,应用程序就再次激活。

当内存资源短缺时,Windows可以终止暂停应用程序的进程,从而终止该应用程序。应用程序不会收到任何消息,所以不能对此事件做出反应。因此,应用程序应该在进入暂停模式前做一些处理工作,保存其状态。等到应用程序终止时进行处理就晚了。

当收到暂停事件时,应用程序应该将其状态存储在磁盘上。如果再次启动应用程序,应用程序可以显示给用户,好像它从未终止。只需要把页面堆栈的信息存储到用户退出的页面上,恢复页面堆栈,并把字段初始化为用户输入的数据,就允许用户返回。

本节的示例应用程序ApplicationLifeline就完成这个任务。在这个程序中,允许在多个页面之间的导航,可以输入状态。应用程序暂停时,存储页面堆栈和状态,在启动应用程序时恢复它们。

1. 应用程序的执行状态

应用程序的状态使用ApplicationExecutionState枚举定义。该枚举定义了NotRunning、Running、Suspended、Terminated和CloseByUser状态。应用程序需要知道并存储自己的状态,因为用户在返回应用程序时希望继续原来的操作。

在App类的OnLaunched方法中,可以使用LauchActivatedEventArgs参数的PreviousExecutionState属性获取应用程序的前一个执行状态。如果应用程序是在安装后第一次启动,在重启计算机后启动,或者用户上一次在任务管理器中终止了其进程,那么该应用程序的前一个状态是NotRunning。如果用户单击应用程序的图标时应用程序已经激活,或者应用程序通过某个激活协定激活,则其前一个执行状态为Running。如果应用程序被暂停,那么激活它时PreviousExecutionState属性会返回Suspended。一般来说,在这种情况下不需要执行什么特殊操作。因为状态仍然在内存中可用。在暂停状态下,应用程序不使用CPU循环,也没有磁盘访问。

注意:

应用程序可以实现一个或多个协定,然后用其中一个协定激活应用程序。这类协定的一个例子是共享,使用这个协定,用户可以共享另一个应用程序的一些数据,并使用它作为共享目标,启动一个Windows应用程序。实现共享协定参见本章的"共享数据"一节。

2. 在页面之间导航

展示Windows应用程序的生命周期的示例应用程序(ApplicationLifetime)从Blank App模板开始。创建项目后,添加页面Page 1和Page 2,实现页面之间的导航。

在MainPage中,添加两个按钮控件来导航Page 2和Page 1,再添加两个文本框控件,在导航时传递数据:

        <StackPanel Spacing="5">
            <Button Content="Page 1" Click="{x:Bind GoToPage1,Mode=OneTime}"/>
            <TextBox Header="Parameter 1" Text="{x:Bind ParameterPage1,Mode=TwoWay}"/>
            <Button Content="Page 2" Click="{x:Bind GoToPage2,Mode=OneTime}"/>
            <TextBox Header="Parameter 2" Text="{x:Bind ParameterPage2,Mode=TwoWay}"/>
        </StackPanel>

代码隐藏文件包含事件处理程序、Page 1和Page 2的导航代码,以及参数的属性:

        public string ParameterPage1 { get; set; }
        public string ParameterPage2 { get; set; }
        public void GoToPage1() => Frame.Navigate(typeof(Page1), ParameterPage1);
        public void GoToPage2() => Frame.Navigate(typeof(Page2), ParameterPage2);

Page 1的UI元素显示在导航到这个页面时接收到的数据、允许用户导航到Page 2的按钮,以及允许用户输入一些状态信息的一个文本框,应用程序终止时会保存这些状态信息:

        <StackPanel Spacing="5">
            <TextBlock Text="Page 1" Style="{StaticResource HeaderTextBlockStyle}"/>
            <TextBlock Text="{x:Bind ReceivedContent,Mode=OneTime}" Style="{StaticResource BodyTextBlockStyle}"/>
            <TextBox Text="{x:Bind Parameter,Mode=TwoWay}"/>
            <Button Content="Navigate to Page 2" Click="{x:Bind GoToPage2,Mode=OneTime}"/>
            <!--<TextBox Header="Session State 1" Text="{x:Bind Data.Session1,Mode=TwoWay}"/>
            <TextBox Header="Session State 2" Text="{x:Bind Data.Session2,Mode=TwoWay}"/>-->
        </StackPanel>

类似于MainPage ,Page 1的导航代码为导航时传递的数据定义了一个自动实现的属性,和实现导航到Page 2的一个事件处理程序:

        public void GoToPage2() => Frame.Navigate(typeof(Page2), Parameter);
        public string Parameter { get; set; }

在代码隐藏文件中,导航参数在OnNavigatedTo()方法的重写版本中接收。接收到的参数分配给自动实现的属性ReceivedContent:

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            ReceivedContent = e.Parameter?.ToString();
        }

        public string ReceivedContent { get; set; }

在导航的实现代码中,Page 2非常类似于Page 1,所以这里不重复它的实现。

这里,标题栏后退按钮的可见性和处理程序在类BackButtonManager中定义。如果当前Frame的CanGoBack属性返回true,那么构造函数的实现代码使后退按钮可见。如果堆栈可用,就实现OnBackRequested方法,返回页面堆栈:

    public class BackButtonManager : IDisposable
    {
        private SystemNavigationManager _navigationManager;
        private Frame _frame;
        public BackButtonManager(Frame frame)
        {
            _frame = frame ?? throw new ArgumentNullException(nameof(frame));
            _navigationManager = SystemNavigationManager.GetForCurrentView();
            _navigationManager.AppViewBackButtonVisibility = _frame.CanGoBack ?
                AppViewBackButtonVisibility.Visible :
                AppViewBackButtonVisibility.Collapsed;
            _navigationManager.BackRequested += OnBackRequested;
        }
        private void OnBackRequested(object sender, BackRequestedEventArgs e)
        {
            if (_frame.CanGoBack)
            {
                _frame.GoBack();
                e.Handled = true;
            }
        }
        public void Dispose()
        {
            _navigationManager.BackRequested -= OnBackRequested;
        }
    }

在所有的页面中,通过在OnNavigatedTo方法中传递Frame来实例化BackButtonManager,它在OnNavigatedFrom方法中销毁:

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            _backButtonManager = new BackButtonManager(Frame);
        }
        protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
        {
            base.OnNavigatingFrom(e);
            _backButtonManager.Dispose();
        }

有了所有这些代码,用户可以在3个不同的页面之间后退和前进。下一步需要记住页面和页面堆栈,把应用程序导航到用户最近一次访问的页面上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值