Prism MVVM - PageDialogService:警告說明

還記得先前在練習《從 Xamarin.Forms 存取 RESTful API》時,曾說明底下這段讀取 REST API 的程式不太理想。

public async void OnNavigatedTo(NavigationParameters parameters)
{
    if (Addresses == null)
    {
        try
        {
            var result = await _apiService.GetAddresses();
            Addresses = new ObservableCollection<AddressModel>(result);
        }
        catch (System.Exception)
        {
            throw;
        }
    }
}    

因為上述的程式當讀取失敗時並末做出任何處理,而是以 throw;  把例外擲出,當真正遇到讀取失敗時,這樣的寫法會造成應用程式發生閃退的情況。今天在試玩昨天就做的成品,想再往下發展時,很不幸的 Azure 免費點數用完了,造成 Azure Web App 被停用,果然發生閃退,所以今天就先來學習如何解決。

使用者應該有權發生什麼事

雖然把上述的程式把 throw;  拿掉,保持 catch () { } 區塊空白就不會發生閃退了,但這對使用者很不友善,使用者可能會癡癡地等資料送過來,雖然發生的例外使用者也無法自行解決(可能連程式設計人員也暫時無法解決),但是出現個訊息通知一下總是好的。

雖然 Xamarin.Forms 有自己的顯示訊息的方法,但是我們已採用了 MVVM 的開發模式,要將這些原本實作在 Page 上的,不經過一些苦工不太容易在 ViewModel 中使用,好在 Prism MVVM Framework 已經幫我們做好苦工了,有個 PageDialogService 可以將顯示訊息的方法包裝到 ViewModel  使得與 View 之間的耦合度切開。

PageDialogService 主要提供三揰型式的跳出對話框(Pop-ups Dialog):

  1.  用來顯示警告或是說明訊息
  2.  用來讓使用者作確認選擇(是/否)
  3.  用來讓使用者有多數選項的選擇

今天就先來學習在讀取 REST API 發生錯誤時,以訊息框通知使用者。

設定 PageDialogService

請在欲使用 PageDialogService 的 ViewModel (本例例是 MyFirstPageViewModel)的建構函式中加入設定,如下所示:

private IAddressService _apiService;
private INavigationService _navigationService;
private IPageDialogService _pageDialogService;
public MyFirstPageViewModel(
    IAddressService apiService,
    INavigationService navigationService,
    IPageDialogService pageDialogService)
{
    _apiService = apiService;
    _navigationService = navigationService;
    _pageDialogService = pageDialogService;
}

接著在原先的 catch 區塊加入 await _pageDialogService.DisplayAlertAsync("讀取錯誤", e.StatusCode.ToString(), "朕知道了"); 的顯示訊息方法,如下所示:

public async void OnNavigatedTo(NavigationParameters parameters)
{
    if (Addresses == null)
    {
        try
        {
            var result = await _apiService.GetAddresses();
            Addresses = new ObservableCollection<AddressModel>(result);
        }
        catch (DemaeApiException e)
        {
            if (e.Connection)
                await _pageDialogService.DisplayAlertAsync("讀取錯誤", e.StatusCode.ToString(), "朕知道了");
            else
                await _pageDialogService.DisplayAlertAsync("連線錯誤", e.StatusCode.ToString(), "朕知道了");
        }
    }
}

還記得先前實作例外處理時,有提到例外的發生可能是連線問題,也有可能是 REST API 本身的問題,所以可以使用 if (e.Connection) 來區分,而 DisplayAlertAsync() 方法傳入三個字串型別的參數,這三個參數分別為:

  1.  對方框的抬頭文字
  2.  訊息內容
  3.  按鈕文字

完成後執行畫面如下,果然是 Azure Web App 被停用,造成連線錯誤:

好吧!今天就學習到這裡,明天在來學習要刪除地址資料時,先讓使用者確認,確認後才刪,否則不刪。