2017/6/20

Xamarin.Forms 教學系列文(十八.貳 - 1)MVVM - ViewModel LifeCycle

接續上一小節的計算機,

遇到的問題:
當手機應用程式突然關閉 (例如突然有人打電話來),再重新打開應用程式時,剛剛用計算機算到一半的值還會在嗎??

真相是... 那值被電話 Gank 一下就不見了...

簡單來說:
當 App 被中斷後重啟,希望看到 ViewModel 的值,是中斷前操作的結果吧!!

這邊將配合 第六章 講到的 Application.Current.Properties,來實作 ViewModel 復活大法。


接續上一小節的 AdderViewModel,另外寫了兩個方法 SaveState RestorState

SaveState 將要復原的值存到 dictionary,
RestorState 將值從 dictionary 挖出來放回 ViewModel

要注意這兩個方法都會在 App.cs 使用並將 dictionary 傳入

public class AdderViewModel : ViewModelBase
{
    …

    // 儲存目前的值到 dictionary
    public void SaveState(IDictionary dictionary)
    {
        dictionary["CurrentEntry"] = CurrentEntry;
        dictionary["HistoryString"] = HistoryString;
        dictionary["isSumDisplayed"] = isSumDisplayed;
        dictionary["accumulatedSum"] = accumulatedSum;
    }

    // 從 dictionary 還原 App 中斷前的值
    public void RestoreState(IDictionary dictionary)
    {
        CurrentEntry = GetDictionaryEntry(dictionary, "CurrentEntry", "0");
        HistoryString = GetDictionaryEntry(dictionary, "HistoryString", "");
        isSumDisplayed = GetDictionaryEntry(dictionary, "isSumDisplayed", false);
        accumulatedSum = GetDictionaryEntry(dictionary, "accumulatedSum", 0.0);

        RefreshCanExecutes();
    }

    // 泛型方法
    public T GetDictionaryEntry(IDictionary dictionary, string key, T defaultValue)
    {
        if (dictionary.ContainsKey(key))
            return (T)dictionary[key];

        return defaultValue;
    }
}


這兩個方法,當然要在 App() 和 OnSleep() 使用~
才能控制在 App 中斷或復原時去執行:
public class App : Application
{
    AdderViewModel adderViewModel;

    public App()
    {
        // 初始化 ViewModel
        adderViewModel = new AdderViewModel();

        // 還原儲存的值
        adderViewModel.RestoreState(Current.Properties);
        MainPage = new AddingMachinePage(adderViewModel);
    }

    protected override void OnStart()
    {
        // Handle when your app starts.
    }

    protected override void OnSleep()
    {
        // Handle when your app sleeps.
        adderViewModel.SaveState(Current.Properties);
    }

    protected override void OnResume()
    {
        // Handle when your app resumes. 
    }
}


書上提到,這種儲存狀態的方法並非唯一,甚至你可以自己在 ViewModel 內定義自己的 OnSleep 事件。

一個應用程式內可能有相當多個 ViewModel,而存進 Dictionary 的 key 不能重複,這邊建議可以在 key 值加上 Class 名字來避免重複,像是:AdderViewModel.CurrentEntry





沒有留言:

張貼留言