【发布时间】:2021-08-04 17:19:15
【问题描述】:
我正在使用 Jetpack 库开发一个安卓应用:
- 刀柄
- 导航
- 视图模型
- 数据绑定
其实我对MVP模式很熟悉。
我正在尝试研究 MVVP 模式(数据绑定和 Jetpack ViewModel)
我有 2 个片段(A 和 B)。
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
@AndroidEntryPoint
class AFragment {
private val viewModel: AViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.viewModel = viewModel
with(binding) {
button.setOnClickListener {
this@AFragment.viewModel.doAction()
}
}
viewModel.result.observe(viewLifecycleOwner) { result ->
findNavController().navigate(AFragmentDirections.actionAFragmentToBFragment(result))
}
}
}
这里是 AViewModel:
@HiltViewModel
class AViewModel @Inject constructor(): ViewModel() {
private val _result: MutableLiveData<Int> = MutableLiveData()
val result: LiveData<Int>
get() = _result
fun doAction() {
_result.postValue(SOME_ACTION_RESULT)
}
}
它正确显示了 BFragment。
但是如果我在 BFragment 上触摸Back Button,它仍然会显示 BFragment。
实际上,它回到了AFragment,但又回到了BFragment。
当我在 BFragment 上触摸 Back Button 时,
- AFragment 再次启动(我检查过 onViewCreated() 是否被再次调用)
- 再次调用以下观察代码:
viewModel.result.observe(viewLifecycleOwner) { result ->
findNavController().navigate(AFragmentDirections.actionAFragmentToBFragment(result))
}
为什么会再次调用这段代码?
我是否正确编写代码?
最佳做法是什么?
现在,我找到了解决办法。
在 A 片段中:
viewModel.result.observe(viewLifecycleOwner) { result ->
if (result != null) {
findNavController().navigate(AFragmentDirections.actionAFragmentToBFragment(result))
viewModel.resetResult()
}
}
在 AViewModel 中:
fun resetResult() {
_result.postValue(null)
}
使用此代码,它可以正常工作。
是的...但是我不喜欢这段代码...
这……太奇怪了……
我不知道什么是最佳实践...
【问题讨论】:
-
在结果上放一个断点来检查当你按下返回时它是否改变了。每次更改时,都会调用导航到另一个片段的代码。如果是这种情况,为什么不使用布尔值来确定它是否应该导航?
-
doAction() 函数只被调用一次,永远不会再被调用。
标签: android mvvm android-databinding android-viewmodel android-navigation