2016-07-28 92 views
3

我在我的ViewModel中有一個排序問題,這似乎與線程有關,但我無法完全弄清楚我們發生了什麼問題或者我的「修復」是如何修復它的。MvvmCross ShowViewModel加載順序

我有一個ViewModel需要調用異步方法來加載其初始數據。我從MvvmCross自動調用的Init方法調用異步方法。如果加載失敗,出於任何原因,我想顯示一個錯誤屏幕,但調用Init方法內部的ShowViewModel不會產生預期的結果。正確調用ShowViewModel,但是在調試器中跟蹤它,看起來ErrorViewModel在原始ViewModel/View完成加載之前顯示 - 因此加載但未出現,因爲它被原始ViewModel覆蓋。

下面是加載代碼的簡化版本:

public async Task Init() 
{ 
    await LoadInitialDataAsync(); 
} 

protected async Task LoadInitialDataAsync() 
{ 
    var loadResult = await LoadSomeStuffAsync(); 
    if (loadResult.IsBadNews) 
    { 
     ShowViewModel<ErrorViewModel>(); 
     return; 
    } 
} 

的MvxTrace日誌告訴我,ShowViewModel叫上ErrorViewModel它被稱爲初始視圖模型後,但只有最初的視圖顯示,而不是ErrorView。

要「解決」這個問題,我可以做兩件事情之一。

我可以包裝在Task.Run調用LoadInitialDataAsync:

await Task.Run(async() => 
{ 
    await LoadInitialDataAsync(); 
}); 

或者,我可以內ShowViewModel呼叫之前增加一個小的延遲:

protected async Task LoadInitialDataAsync() 
{ 
    var loadResult = await LoadSomeStuffAsync(); 
    if (loadResult.IsBadNews) 
    { 
     await Task.Delay(1); 
     ShowViewModel<ErrorViewModel>(); 
     return; 
    } 
} 

無論這些變化的產生期望的結果 - 如果在加載過程中發生錯誤事件,ErrorViewModel將顯示其視圖。

問題是,我不相信這個修復程序,因爲我不明白在諺語下有什麼問題,因此不知道這個修復程序有多強大。這似乎是一個任意時間的事情,它將在最不方便的時間在未來某個時候再次突破。

如果有人明白MvvmCross的內部結構足以幫助解決這個問題,我會很感激!

+0

你能否提供一個repo/sample來重現這個問題?使用上面的簡化版本似乎不會導致發生此問題。 – Plac3Hold3r

+0

我有同樣的問題,沒有人在「答案」似乎明白。問題在於,在CORE項目中,您有一些任務需要等待,並且您希望在該等待期間顯示「加載程序」?對?你找到了解決方案嗎? – Ph0b0x

回答

3

Init方法應該做的很少。 Init通常用於複製傳入ShowViewModel<TViewModel>()的一些導航參數。 Start方法是您打算執行ViewModel啓動的地方,例如調用LoadInitialDataAsync。請查閱App Lifecycle documentation瞭解更多信息。

+0

謝謝,文檔很有幫助。但是,我嘗試使用Start()而不是Init(),行爲完全相同。 –

0

基於https://github.com/MvvmCross/MvvmCross/wiki/viewmodel--to-viewmodel-navigation

當您的應用程序顯示一個ViewModel頁面,說FirstViewModel,然後 是第一頁可以請求顯示器向前移動到 新視圖模型頁面,說SecondViewModel使用一個電話,如:

ShowViewModel<SecondViewModel>(); 

當FirstViewModel提出此請求,那麼MvvmCross 框架將:

  • 找到一個視圖作爲「頁面」爲SecondViewModel在應用程序中使用 - 通常這將是SecondView
  • 創建此SecondView的新實例
  • 創建SecondViewModel並提供它作爲DataContext的新SecondView
  • 要求操作系統顯示SecondView

ShowViewModel<ErrorViewModel()你被調用,同時又顯示初始視圖處理不當,這可能是國際空間站用於它並適合您的調試器行爲。

延遲使它有足夠的時間顯示,異步任務不會阻止它,所以它顯示,然後顯示完成,它切換到另一個視圖。

一個選項可能會做之前的初始化和傳遞與ShowViewModel的數據,但我沒有經驗。 或者保存錯誤狀態,讓視圖從視圖中加載並調用viewmodel,讓它在創建後切換。

雖然iam並不是那些粉絲之一,但這就是爲什麼我在通過服務進行初始化之前以及在切換到新視圖模型之前無法做出反應。

不知道你現在的結構有多複雜,哪種結果最好。