Windows Phone 8.1 應(yīng)用生命周期
一、“后退鍵”不會(huì)終止應(yīng)用
關(guān)于 Windows Phone 8.1 的應(yīng)用生命周期,***個(gè)要知道的關(guān)鍵就是:“后退鍵”不會(huì)終止應(yīng)用!
在 8.0 時(shí)代,不斷的按下“后退鍵”就可以完全的關(guān)閉并且終止應(yīng)用,但在 8.1 中,這樣的行為只會(huì)讓應(yīng)用處在 Suspended(掛起)狀態(tài),可以通過長(zhǎng)按“后退鍵”進(jìn)入多任務(wù)界面查看。
那如果還想像 8.0 一樣終止應(yīng)用呢?(雖然不推薦也沒有必要)可以在多任務(wù)界面點(diǎn)擊應(yīng)用右上角的“叉叉”或者向下滑。
二、應(yīng)用生命周期
應(yīng)用的三個(gè)狀態(tài)分別是:
A:NotRunning
也就是還沒開啟過應(yīng)用,在多任務(wù)界面沒有該應(yīng)用時(shí)。
B:Running
在屏幕上顯示的應(yīng)用就是 Running 狀態(tài),同時(shí)只會(huì)有 1 個(gè)應(yīng)用處于 Running 狀態(tài)。
C:Suspended
不在屏幕上顯示并能在多任務(wù)界面查看的應(yīng)用則處于 Suspended(掛起)狀態(tài)。
三種狀態(tài)間切換的操作:
(1)NotRunning -> Running
要從 NotRunning 切換到 Running 狀態(tài),其實(shí)也就是開啟應(yīng)用,可通過點(diǎn)擊應(yīng)用磁貼、應(yīng)用間協(xié)議啟動(dòng)、Cortana等方式。
在狀態(tài)的切換過程中會(huì)觸發(fā) OnLaunched 事件。
(2)Running -> Suspended
當(dāng)應(yīng)用不再占據(jù)屏幕時(shí)則從 Running 切換到 Suspended 狀態(tài),可以是“Win”鍵、“返回鍵”,有電話打來時(shí)也會(huì)掛起。
在狀態(tài)的切換過程中會(huì)觸發(fā) OnSuspending 事件。
(3)Suspended -> Running
如果在應(yīng)用掛起狀態(tài)時(shí)沒有因?yàn)槟承┰颍ū热鐑?nèi)存不足)導(dǎo)致應(yīng)用終止的話,點(diǎn)擊磁貼或者多任務(wù)切換都會(huì)讓應(yīng)用從 Suspender 返回到 Running 狀態(tài)。
在狀態(tài)的切換過程中會(huì)依次觸發(fā) OnResuming 和 OnLaunched 事件。
(4)Suspended -> NotRunning
如果在應(yīng)用掛起狀態(tài)時(shí)因?yàn)槟承┰颍ū热鐑?nèi)存不足)導(dǎo)致應(yīng)用終止的話,則會(huì)從 Suspended 變成 NotRunning 狀態(tài)。
在這過程不會(huì)觸發(fā)任何事件。
#p#
三、OnSuspending
因?yàn)閼?yīng)用在掛起狀態(tài)時(shí),并不能預(yù)測(cè)應(yīng)用是否會(huì)因?yàn)槟承┰颍ū热鐑?nèi)存不足)而終止,而在這終止過程中也沒有事件讓開發(fā)者處理應(yīng)用數(shù)據(jù),所以只能在應(yīng)用將要掛起時(shí)準(zhǔn)備。因此 OnSuspending 事件變得十分重要。
若要使用 OnSuspending 方法則先要在構(gòu)造函數(shù)中添加對(duì)其的引用:
- public App()
- {
- this.InitializeComponent();
- this.Suspending += OnSuspending;
而在 OnSuspending 方法中可以根據(jù)需要保存頁面數(shù)據(jù),比如輸入框內(nèi)的文本、頁面導(dǎo)航歷史等,可以通過保存在應(yīng)用獨(dú)立存儲(chǔ)中或利用 NavigationHelper 和 SuspensionManager 類等:
- async void OnSuspending(object sender, SuspendingEventArgs e)
- {
- SuspendingDeferral deferral = e.SuspendingOperation.GetDeferral();
- await this.SaveStateToLocalFile(Data.Value);
- await SuspensionManager.SaveAsync();
- deferral.Complete();
如果只想保存某個(gè)頁面的信息則可以在 SaveState 中保存
- private void NavigationHelper_SaveState(object sender, SaveStateEventArgs e)
- {
- e.PageState["isEditing"] = true;
- e.PageState["currentText"] = this.viewModel.DataItem.Title;
- }
NavigationHelper 和 SuspensionManager 類是添加基本頁時(shí) Visual Studio 自動(dòng)添加的
#p#
- public class NavigationHelper : DependencyObject
- {
- private Page Page { get; set; }
- private Frame Frame { get { return this.Page.Frame; } }
- public NavigationHelper(Page page)
- {
- this.Page = page;
- this.Page.Loaded += (sender, e) =>
- {
- WINDOWS_PHONE_APP
- Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
- e
- if
- };
- this.Page.Unloaded += (sender, e) =>
- {
- WINDOWS_PHONE_APP
- Windows.Phone.UI.Input.HardwareButtons.BackPressed -= HardwareButtons_BackPressed;
- e
- if
- };
- }
- #region Navigation support
- RelayCommand _goBackCommand;
- RelayCommand _goForwardCommand;
- public RelayCommand GoBackCommand
- {
- get
- {
- if (_goBackCommand == null)
- {
- _goBackCommand = new RelayCommand(
- () => this.GoBack(),
- () => this.CanGoBack());
- }
- return _goBackCommand;
- }
- set
- {
- _goBackCommand = value;
- }
- }
- public RelayCommand GoForwardCommand
- {
- get
- {
- if (_goForwardCommand == null)
- {
- _goForwardCommand = new RelayCommand(
- () => this.GoForward(),
- () => this.CanGoForward());
- }
- return _goForwardCommand;
- }
- }
- public virtual bool CanGoBack()
- {
- return this.Frame != null && this.Frame.CanGoBack;
- }
- public virtual bool CanGoForward()
- {
- return this.Frame != null && this.Frame.CanGoForward;
- }
- public virtual void GoBack()
- {
- if (this.Frame != null && this.Frame.CanGoBack) this.Frame.GoBack();
- }
- public virtual void GoForward()
- {
- if (this.Frame != null && this.Frame.CanGoForward) this.Frame.GoForward();
- }
- #if WINDOWS_PHONE_APP
- private void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
- {
- if (this.GoBackCommand.CanExecute(null))
- {
- e.Handled = true;
- this.GoBackCommand.Execute(null);
- }
- }
- #else
- private void CoreDispatcher_AcceleratorKeyActivated(CoreDispatcher sender,
- AcceleratorKeyEventArgs e)
- {
- var virtualKey = e.VirtualKey;
- if ((e.EventType == CoreAcceleratorKeyEventType.SystemKeyDown ||
- e.EventType == CoreAcceleratorKeyEventType.KeyDown) &&
- (virtualKey == VirtualKey.Left || virtualKey == VirtualKey.Right ||
- (int)virtualKey == 166 || (int)virtualKey == 167))
- {
- var coreWindow = Window.Current.CoreWindow;
- var downState = CoreVirtualKeyStates.Down;
- bool menuKey = (coreWindow.GetKeyState(VirtualKey.Menu) & downState) == downState;
- bool controlKey = (coreWindow.GetKeyState(VirtualKey.Control) & downState) == downState;
- bool shiftKey = (coreWindow.GetKeyState(VirtualKey.Shift) & downState) == downState;
- bool noModifiers = !menuKey && !controlKey && !shiftKey;
- bool onlyAlt = menuKey && !controlKey && !shiftKey;
- if (((int)virtualKey == 166 && noModifiers) ||
- (virtualKey == VirtualKey.Left && onlyAlt))
- {
- e.Handled = true;
- this.GoBackCommand.Execute(null);
- }
- else if (((int)virtualKey == 167 && noModifiers) ||
- (virtualKey == VirtualKey.Right && onlyAlt))
- {
- e.Handled = true;
- this.GoForwardCommand.Execute(null);
- }
- }
- }
- private void CoreWindow_PointerPressed(CoreWindow sender,
- PointerEventArgs e)
- {
- var properties = e.CurrentPoint.Properties;
- if (properties.IsLeftButtonPressed || properties.IsRightButtonPressed ||
- properties.IsMiddleButtonPressed) return;
- bool backPressed = properties.IsXButton1Pressed;
- bool forwardPressed = properties.IsXButton2Pressed;
- if (backPressed ^ forwardPressed)
- {
- e.Handled = true;
- if (backPressed) this.GoBackCommand.Execute(null);
- if (forwardPressed) this.GoForwardCommand.Execute(null);
- }
- }
- #endif
- #endregion
- #region Process lifetime management
- private String _pageKey;
- public event LoadStateEventHandler LoadState;
- public event SaveStateEventHandler SaveState;
- public void OnNavigatedTo(NavigationEventArgs e)
- {
- var frameState = SuspensionManager.SessionStateForFrame(this.Frame);
- this._pageKey = "Page-" + this.Frame.BackStackDepth;
- if (e.NavigationMode == NavigationMode.New)
- {
- var nextPageKey = this._pageKey;
- int nextPageIndex = this.Frame.BackStackDepth;
- while (frameState.Remove(nextPageKey))
- {
- nextPageIndex++;
- nextPageKey = "Page-" + nextPageIndex;
- }
- if (this.LoadState != null)
- {
- this.LoadState(this, new LoadStateEventArgs(e.Parameter, null));
- }
- }
- else
- {
- if (this.LoadState != null)
- {
- this.LoadState(this, new LoadStateEventArgs(e.Parameter, (Dictionary<String, Object>)frameState[this._pageKey]));
- }
- }
- }
- public void OnNavigatedFrom(NavigationEventArgs e)
- {
- var frameState = SuspensionManager.SessionStateForFrame(this.Frame);
- var pageState = new Dictionary<String, Object>();
- if (this.SaveState != null)
- {
- this.SaveState(this, new SaveStateEventArgs(pageState));
- }
- frameState[_pageKey] = pageState;
- }
- #endregion
- }
- public delegate void LoadStateEventHandler(object sender, LoadStateEventArgs e);
- public delegate void SaveStateEventHandler(object sender, SaveStateEventArgs e);
- public class LoadStateEventArgs : EventArgs
- {
- public Object NavigationParameter { get; private set; }
- public Dictionary<string, Object> PageState { get; private set; }
- public LoadStateEventArgs(Object navigationParameter, Dictionary<string, Object> pageState)
- : base()
- {
- this.NavigationParameter = navigationParameter;
- this.PageState = pageState;
- }
- }
- public class SaveStateEventArgs : EventArgs
- {
- public Dictionary<string, Object> PageState { get; private set; }
- public SaveStateEventArgs(Dictionary<string, Object> pageState)
- : base()
- {
- this.PageState = pageState;
- }
- }
四、OnResuming
既然在 OnSuspending 和 SaveState 方法中保存了必要數(shù)據(jù),就可以在 OnResuming 和 LoadState 方法中獲取之前保存的數(shù)據(jù)
- void OnResuming(object sender, object e)
- {
- Data.Value += this.CalculateOffsetTimeInDecimalSeconds(this.suspensionTime);
- }
- private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
- {
- if ((e.PageState != null) && e.PageState.ContainsKey("isEditing"))
- {
- this.viewModel.SetEditMode();
- this.viewModel.DataItem.Title = e.PageState["currentText"] as string;
- }
- }
五、OnLaunched
首先,在 OnLaunched 方法中可以通過 e.PreviousExecutionState 了解到應(yīng)用之前的狀態(tài)。
狀態(tài)包括:
(1)CloseByUser:被用戶主動(dòng)在多任務(wù)界面中關(guān)閉
(2)NotRunning:沒有啟動(dòng)過
(3)Running:?jiǎn)?dòng)中
(4)Terminated:掛起狀態(tài)時(shí)因內(nèi)存不足被系統(tǒng)終止
(5)Suspended:掛起狀態(tài)
因此,可以通過對(duì)此的判斷,根據(jù)不同情況處理應(yīng)用:
- protected async override void OnLaunched(LaunchActivatedEventArgs e)
- {
- Frame rootFrame = Window.Current.Content as Frame;
- if (rootFrame == null)
- {
- rootFrame = new Frame();
- SuspensionManager.RegisterFrame(rootFrame, "AppFrame");
- rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
- if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
- {
- try
- {
- await SuspensionManager.RestoreAsync();
- }
- catch (SuspensionManagerException)
- {
- }
- }
- Window.Current.Content = rootFrame;
- }
- if (rootFrame.Content == null)
- {
- rootFrame.Navigate(typeof(MainPage), e.Arguments);
- }
- Window.Current.Activate();
- }
六、注意
以上的方法盡量使用異步操作,不要進(jìn)行大量的復(fù)雜操作
本文鏈接:http://www.cnblogs.com/xiaoshi3003/p/3752895.html