簡體   English   中英

"如何在不綁定到 ViewModel (MVVM) 中的 UI 的情況下使用 android 導航?"

[英]How to use android navigation without binding to UI in ViewModel (MVVM)?

我正在使用在 Google I\/O 2018 上展示的 android 導航,似乎我可以通過綁定到某個視圖或使用NavHost<\/code>從 Fragment 獲取它來使用它。 但我需要的是根據幾個條件從我的第一個片段從 ViewModel 導航到另一個特定視圖。 對於ViewModel<\/code> ,我擴展了AndroidViewModel<\/code> ,但我不明白下一步該怎么做。 我無法將getApplication<\/code>轉換為 Fragment\/Activity ,也無法使用NavHostFragment<\/code> 。 此外,我不能只將導航綁定到onClickListener<\/code> ,因為startFragment<\/code>只包含一個ImageView<\/code> 。 如何從ViewModel<\/code>導航?

class CaptionViewModel(app: Application) : AndroidViewModel(app) {
private val dealerProfile = DealerProfile(getApplication())
val TAG = "REGDEB"


 fun start(){
    if(dealerProfile.getOperatorId().isEmpty()){
        if(dealerProfile.isFirstTimeLaunch()){
            Log.d(TAG, "First Time Launch")
            showTour()
        }else{
            showCodeFragment()
            Log.d(TAG, "Show Code Fragment")

        }
    }
}

private fun showCodeFragment(){
    //??
}

private fun showTour(){
    //??
}

}

如何從ViewModel導航?

答案是請不要。 ViewModel旨在存儲和管理與UI相關的數據。

新答案

在我之前的回答中,我說我們不應該從ViewModel導航,原因是因為導航,ViewModel必須引用Activities / Fragments,我相信(也許不是最好的,但我仍然相信它)永遠不會一個好主意。

但是,在Google推薦的應用程序架構中,它提到我們應該從模型中驅動UI 在我想之后,他們對此有何意義?

所以我查看了“android-architecture”中的一個示例,我發現了Google如何做到這一點的有趣方式。

請在這里查看: todo-mvvm-databinding

事實證明,他們確實從模型中驅動UI 但是怎么樣?

  1. 他們創建了一個接口TasksNavigator ,它基本上只是一個導航界面。
  2. 然后在TasksViewModel中 ,他們有對TaskNavigator的引用,因此他們可以直接驅動UI而無需引用Activities / Fragments。
  3. 最后,TasksActivity實現了TasksNavigator以提供每個導航操作的詳細信息,然后將導航器設置為TasksViewModel。

有兩種方法我可以推薦這樣做。

  1. 使用 LiveData 進行通信並告訴片段導航。
  2. 創建一個名為 Router 的類,它可以包含您的導航邏輯和對片段或導航組件的引用。 ViewModel 可以與路由器類進行通信以進行導航。

您可以使用可選的自定義枚舉類型並觀察視圖中的變化:

enum class NavigationDestination {
    SHOW_TOUR, SHOW_CODE_FRAGMENT
}

class CaptionViewModel(app: Application) : AndroidViewModel(app) {
    private val dealerProfile = DealerProfile(getApplication())
    val TAG = "REGDEB"

    private val _destination = MutableLiveData<NavigationDestination?>(null)
    val destination: LiveData<NavigationDestination?> get() = _destination
    
    fun setDestinationToNull() {
        _destination.value = null
    }
    

    fun start(){
        if(dealerProfile.getOperatorId().isEmpty()){
            if(dealerProfile.isFirstTimeLaunch()){
                Log.d(TAG, "First Time Launch")
                _destination.value = NavigationDestination.SHOW_TOUR
            }else{
                _destination.value = NavigationDestination.SHOW_CODE_FRAGMENT
                Log.d(TAG, "Show Code Fragment")

            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM