天天看點

現代作業系統應用開發:UWP——onSuspend:挂起并關閉功能簡介實作效果實作過程總結TipsFYI

  • 功能簡介
  • 實作效果
  • 實作過程
    • 修改App.xaml.cs檔案
    • 在MainPage.xaml中添加控件
    • 在MainPage.xaml.cs中添加代碼
  • 總結
  • Tips
  • FYI

功能簡介

MainPage裡面有一個Image控件和文本框控件,可以更改圖檔和在文本框中輸入内容,Debug模式下選擇生命周期事件中的挂起并關閉,重新打開之後還原之前圖檔的内容和文本框的内容

現代作業系統應用開發:UWP——onSuspend:挂起并關閉功能簡介實作效果實作過程總結TipsFYI

實作效果

  • 啟動
現代作業系統應用開發:UWP——onSuspend:挂起并關閉功能簡介實作效果實作過程總結TipsFYI
  • 更改内容
現代作業系統應用開發:UWP——onSuspend:挂起并關閉功能簡介實作效果實作過程總結TipsFYI
  • 挂起并關閉後再啟動
現代作業系統應用開發:UWP——onSuspend:挂起并關閉功能簡介實作效果實作過程總結TipsFYI

實作過程

修改App.xaml.cs檔案

  • 在類App中添加一個變量,用于判斷是否處于挂起狀态
//App.cs
public bool isSuspend = false;
           
  • 修改OnSuspending函數
private void OnSuspending(object sender, SuspendingEventArgs e)
{
    this.isSuspend = true;
    var deferral = e.SuspendingOperation.GetDeferral();
    //儲存應用程式狀态并停止任何背景活動
    Frame frameState = Window.Current.Content as Frame;
    ApplicationData.Current.LocalSettings.Values["Navigation"] = frameState.GetNavigationState();
    deferral.Complete();
}
           
  • 在OnLaunched函數中添加代碼
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
    Frame rootFrame = Window.Current.Content as Frame;
    if (rootFrame == null)
    {
        rootFrame = new Frame();
        rootFrame.NavigationFailed += OnNavigationFailed;
        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {//添加的代碼
            rootFrame.SetNavigationState((string)ApplicationData.Current.LocalSettings.Values["Navigation"]);
        }
        Window.Current.Content = rootFrame;
    }

    if (e.PrelaunchActivated == false)
    {
        if (rootFrame.Content == null)
        {
            rootFrame.Navigate(typeof(MainPage), e.Arguments);
        }
        Window.Current.Activate();
    }
}
           

在MainPage.xaml中添加控件

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <Image Source="/Assets/RedHood.jpg"></Image>
        <TextBox Text="This is the default content"></TextBox>
        <Button Content="PickPicture" Click="ChangeImage"></Button>
    </StackPanel>
</Grid>
           

在MainPage.xaml.cs中添加代碼

namespace onSuspendSample
{
    public sealed partial class MainPage : Page
    {
        //source和Content用于儲存Image控件的Source和文本框的内容
        private string source = "";
        private string content = "";
        //prefix為LocalFolder的使用字首
        private string prefix = "ms-appdata:///local/";

        public MainPage()
        {
            this.InitializeComponent();
        }

        //改變圖檔的按鈕點選事件
        private async void ChangeImage(object sender, RoutedEventArgs e)
        {
            //挑選圖檔
            var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
            openPicker.FileTypeFilter.Add(".jpg");
            StorageFile file = await openPicker.PickSingleFileAsync();

            //儲存圖檔到LocalFolder
            Windows.Storage.StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
            StorageFile fileCopy = await file.CopyAsync(localFolder, file.Name, NameCollisionOption.ReplaceExisting);
            BitmapImage bitmap = new BitmapImage();
            using (var stream = await fileCopy.OpenAsync(Windows.Storage.FileAccessMode.Read))
            {
                bitmap.SetSource(stream);
            }

            //source儲存圖檔路徑,挂起後重新打開将使用這個值進行還原
            source = prefix + file.Name;

            //設定圖檔控件的Image屬性
            MyImage.Source = bitmap;
        }

        //進入MainPage時調用
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            //判斷是第一次打開還是挂起後打開
            if (e.NavigationMode == NavigationMode.New)
            {
                ApplicationData.Current.LocalSettings.Values.Remove("MainPage");
            }
            else
            {
                if (ApplicationData.Current.LocalSettings.Values.ContainsKey("MainPage"))
                {
                    //還原值
                    ApplicationDataCompositeValue composite = ApplicationData.Current.LocalSettings.Values["MainPage"] as ApplicationDataCompositeValue;
                    source = composite["source"].ToString();
                    content = composite["content"].ToString();
                    ApplicationData.Current.LocalSettings.Values.Remove("MainPage");
                }
                //更新控件
                UpdateWidget();
            }
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            /*
             * OnNavigatedFrom在離開MainPage是會被調用,有可能是跳轉到其他的頁面,也有可能是挂起
             * suspending判斷是否為挂起
             */
            bool suspending = ((App)App.Current).isSuspend;
            if (suspending)
            {
                //如果是,将source,content的值儲存下來,下次再打開的時候還原
                ApplicationDataCompositeValue composite = new ApplicationDataCompositeValue();
                composite["source"] = source;
                composite["content"] = MyTextBox.Text;
                ApplicationData.Current.LocalSettings.Values["MainPage"] = composite;
            }
        }

        //更新控件
        private async void UpdateWidget()
        {
            //根據路徑擷取圖檔
            var uri = new System.Uri(source);
            StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(uri);
            BitmapImage bitmap = new BitmapImage();
            using (var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
            {
                bitmap.SetSource(stream);
            }
            MyImage.Source = bitmap;
            MyTextBox.Text = content;
        }


    }
}
           

需要注意的地方:

  • 代碼中LocalFolder的内容涉及UWP的檔案操作,可以參考另一篇部落格:UWP—檔案操作
  • 更改Image的圖檔後要更新source的值
  • OnNavigatedFrom函數在離開MainPage時調用,該函數中添加的代碼是為了儲存控件的屬性值
  • OnNavigatedTo函數在進入MainPage時調用,如果是在挂起後重新進入MainPage,該函數将使用OnNavigatedFrom中儲存的值還原Source和content,然後再通過UpdateWidget函數更新控件的屬性值

總結

整個挂起并還原的功能最重要的就是兩個部分:

  • App.cs中添加代碼是程式狀态可以儲存
  • 在MainPage的OnNavigatedFrom函數中儲存想要儲存的值,在OnNavigatedTo函數中提取之前儲存的值

Tips

需要注意的是,目前UWP挂起後能儲存的資料必須是能序列化的, 即C#的基本類型,是以在頁面跳轉的時候不能傳遞自定義的類對象(其實就算不使用挂起功能的話也不推薦在頁面跳轉中傳遞自定義的對象,最好隻傳遞基本類型,如果真的要讓兩個頁面共用一個自定義的類對象的話,可以使用單例模式啊V●ᴥ●V)

FYI

項目下載下傳:onSuspendSample

項目下載下傳之後記住把Debug模式從ARM換成X86或X64(根據你自己的機型選擇),之前一開始學習的時候不知道這一點,從網上下載下傳下來的項目都運作不了,糾結的一逼(╥╯^╰╥)

現代作業系統應用開發:UWP——onSuspend:挂起并關閉功能簡介實作效果實作過程總結TipsFYI

繼續閱讀