【问题标题】:Handle navigation in android mvvm在 android mvvm 中处理导航
【发布时间】:2019-12-05 17:47:13
【问题描述】:

我正在构建一个 android 应用程序,但我不确定如何在 MVVM 架构中实现导航。 我采取的第一种方法是将点击事件按钮绑定到 ViewModel 中的一个函数,该函数在必要时执行一些逻辑(例如一些数据验证),然后触发一个 LiveData 事件(告诉视图导航到不同的屏幕)到观察 ViewModel 的视图。

<button android:id="@+id/btnId"
        android:onClick="@{(v) -> myViewModel.onSaveClick()}"
        .../>
class MyViewModel : ViewModel() {
    val saveNavigation = MutableLiveData<Event<Customer>>()
    val errorMessage = MutableLiveData<Event<String>>()

    fun onSaveClick() {
        if (validateCustomer(customer)) {
            repository.save(customer)
            saveNavigation.value = Event(customer)
        }
        else
            errorMessage.value = Event("error")
    }
}

class View : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        //observe event protects from re-reading the value on screen rotation
        myViewModel.saveNavigation.observeEvent(this) {
             findNavController().navigate(CustomerViewDirections
                    .actionCustomerInfoToCustomerBalanceHistory(it))
        }

        myViewModel.errorMessage.observeEvent(this) { toast(it) }
    }
}

第二种方法是视图注册到 onClickListener 并主动调用 ViewModel 逻辑函数(例如验证),然后视图才进行导航

class MyViewModel : ViewModel() {

    fun save() : Status {
        if (validateCustomer(customer)) {
            repository.save(customer)
            return Status.OK
        }
        else
            return Status.Error //or some string message
    }
}

class View : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        btnId.setOnClickListener {
            if (myViewModel.save() == Status.OK) 
                findNavController().navigate(CustomerViewDirections
                    .actionCustomerInfoToCustomerBalanceHistory(myViewModel.customer))
            else
                toast("error")
        }
    }
}

这两种方式中哪一种更适合 MVVM 架构,或者可能还有其他选择?

【问题讨论】:

    标签: android mvvm viewmodel android-livedata


    【解决方案1】:

    我建议您创建一个 Navigator 接口,使用您选择的依赖注入将其注入到您的 ViewModel 中。然后,您在处理导航的组件中实现该接口。然后,您将使用该 Navigator 界面中的方法进行导航。

    例如,

    interface Navigator {
        fun navigateToSettings()
    }
    
    class NavigatorImpl : Navigator {
        override fun navigateToSettings() {
            TODO()
        }
    }
    

    【讨论】:

    • 如何获得对NavigatorImpl 内的NavController 的引用?我在我的视图中使用view.findNavController().navigate(actionId)(尴尬地从 ViewModel 重新路由回 clickListener 内的视图)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    • 2014-12-05
    • 1970-01-01
    相关资源
    最近更新 更多