【问题标题】:How to use android navigation without binding to UI in ViewModel (MVVM)?如何在不绑定到 ViewModel (MVVM) 中的 UI 的情况下使用 android 导航?
【发布时间】:2018-11-17 08:11:09
【问题描述】:

我正在使用在 Google I/O 2018 上展示的 android 导航,我似乎可以通过绑定到某个视图或使用 NavHost 从 Fragment 获取它来使用它。但我需要的是根据几个条件从我的第一个片段从 ViewModel 导航到另一个特定视图。对于ViewModel,我扩展AndroidViewModel,但我不明白下一步该怎么做。我无法将getApplication 转换为片段/活动,也无法使用NavHostFragment。我也不能只将导航绑定到onClickListener,因为startFragment 只包含一个ImageView。如何从ViewModel 导航?

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(){
    //??
}

}

我的片段

class CaptionFragment : Fragment() {
private lateinit var viewModel: CaptionViewModel
private val navController by lazy { NavHostFragment.findNavController(this) }

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
    viewModel = ViewModelProviders.of(this).get(CaptionViewModel::class.java)
    return inflater.inflate(R.layout.fragment_caption, container, false)
}


override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)

    viewModel.start()

}

}

我想在 ViewModel 中保留导航逻辑

【问题讨论】:

  • Navigation 库是一个主要的 UI 组件,您需要将 UI 逻辑保留在 UI 中,因此您需要在 Fragment/Activity 中执行导航
  • 我将在那里加载一些后端负载,并根据它们知道去哪里。一定有办法做到这一点
  • 然后您需要将这些选项作为状态传播到 UI 并在那里做出决定。 ViewModel 不应该对视图一无所知,因此它的架构方式只是将数据发送到将订阅其数据的某个视图。也许您正在寻找 ViewModel 可以主动更改 View 的架构。那将是一个 MVP 架构,演示者可以主动更改视图
  • 尽管我尝试在 Fragment 类中进行导航,但出现了错误 FragmentManager is already executing transactions
  • 我同意@LeviAlbuquerque 所说的一切。还没有看到你的代码,但这可能是issue,它将在 alpha02 中修复

标签: android mvvm kotlin android-navigation android-jetpack


【解决方案1】:

如何从 ViewModel 导航?

答案是请不要。 ViewModel 旨在存储和管理与 UI 相关的数据。

新答案

在我之前的回答中,我说过我们不应该从 ViewModel 导航,原因是因为要导航,ViewModel 必须有对活动/片段的引用,我相信(也许不是最好的,但我仍然相信) 绝不是一个好主意。

但是,在 Google 推荐的应用架构中,它提到我们应该从模型驱动 UI。然后我想了想,它们是什么意思?

所以我检查了“android-architecture”中的一个示例,我发现了一些有趣的 Google 是如何做到的。

请在此处查看:todo-mvvm-databinding

事实证明,它们确实从模型驱动 UI。但是怎么做呢?

  1. 他们创建了一个界面TasksNavigator,基本上只是一个导航界面。
  2. 然后在 TasksViewModel 中,他们引用了 TaskNavigator,因此他们可以驱动 UI,而无需直接引用活动/片段。
  3. 最后,TasksActivity 实现了 TasksNavigator 以提供每个导航操作的详细信息,然后将 navigator 设置为 TasksViewModel。

【讨论】:

  • 为什么应用的导航状态是View的责任? View 的职责是显示数据,而不是知道接下来要显示什么屏幕。
  • 我没有说这是视图的责任。但这也不是 ViewModel 的责任。在 ViewModel 中导航从来都不是一个好主意。
  • ViewModel 是导航的正确位置,只是在 Android 中成为问题,因为我们需要访问视图来执行此导航。也没有抽象导航的好方法。所以,一般来说,Android 上的 VM 无法轻松完成导航,但在其他平台上可以。
  • 出于兴趣,我更喜欢 Yosi 当前的回答。我们一直在使用 Cicerone,它有一个 Router 对象,提供了从 ViewModel 执行导航的访问权限,而且效果很好。在某些时候,我可能需要看看将 Cicerone 与导航组件集成需要什么。
  • 我可能错了或迟到了,但该策略不会将对视图的引用传递给视图模型吗?这可能导致内存泄漏
猜你喜欢
  • 2014-12-31
  • 2011-12-04
  • 2016-05-04
  • 1970-01-01
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 2017-11-28
  • 2019-10-16
相关资源
最近更新 更多