我试图找出如何以最好的方式完成一个活动从ViewModel。我找到了一种方法,使用LiveData对象并发出“信号”。
我怀疑这个解决方案有开销。那么是正确的解决方案还是我应该使用更准确的?
所以去例子:让我们假设在一个应用程序中有一个活动MainActivity和视图模型,如下所示:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val model = ViewModelProviders.of(this).get(MainViewModel::class.java)
model.shouldCloseLiveData.observe(this, Observer { finish() })
}
}
作为MainActivity的伴侣,是一个MainViewModel,如下所示:
class MainViewModel(app: Application) : AndroidViewModel(app) {
val shouldCloseLiveData = MutableLiveData<Void>()
fun someAction(){
shouldCloseLiveData.postValue(null)
}
}
5条答案
按热度按时间8yoxcaq71#
我和你一样认为这个解决方案看起来不整洁,原因有两个。* 首先 * 使用
MutableLiveData
对象来通知事件是一种解决方法。没有数据更改。* 第二 * 将LiveData暴露到视图模型的外部通常违反了 * 封装 * 的原则。我仍然对这个丑陋的android概念感到惊讶。它们应该提供一个选项来观察视图模型,而不是内部的
LiveData
对象。我尝试使用
WeakReference
s来实现观察者模式。这个不稳定。以不可预知的方式,WeakReference
的引用丢失(null
),在这种情况下,不可能调用finish()
。这是令人惊讶的,因为我不认为活动是垃圾收集,而运行。所以这是一个部分的答案排除。作为
WeakReference
实现的观察者模式似乎无法替代您的建议。我想知道如果我在
onStop()
或onDestroy()
期间删除引用,通过硬引用实现观察者模式是否合法。我问了这个问题here。9udxz4iz2#
您可以使用单一事件,如您在此处看到的实现:https://gist.github.com/JoseAlcerreca/5b661f1800e1e654f07cc54fe87441af#file-event-kt
因此,您不必更改活动的实现
视图模型将类似于
0x6upsns3#
我遇到了类似的问题:我有两个Activity(A和B),它们的视图模型连接到一个对象(数据库中的一个表):从一个可观察的实时数据,我必须导航到另一个活动B(从A到B)。问题是,在调用新活动B之后,B中的可观察对象改变了被观察对象中的值。活动A仍然活动,其活动数据再次调用导航代码到B。在一个无限循环中
经过一些研究,我意识到运行
finish
方法并不意味着该活动真的是destroyed。解决方案是,在可观察代码中,从实时数据中删除与特定活动相关的可观察数据。
我在下面的代码片段中展示了它。它是用Java写的,但我认为你读起来没有问题。有了这个,我解决了我的问题。
我认为您可以很容易地在代码中适应这种情况。希望能帮上忙。
0aydgbwb4#
编辑:
更好的方法是使用KotlinChannels。我将在这个示例中使用LiveData,但您也可以直接使用Flow。
视图模型:
在活动方面:
上一个答案(不太好):
我同意,似乎没有一个很好的解决方案,你的建议确实工作得很好。但我建议如下。
因为你使用的是Kotlin,你可以像这样从你的activity传递一个函数到viewmodel:
视图模型:
Activity:这里使用button(和clicklistener)作为示例,但它可以出现在activity代码中的任何位置。
block
函数本质上将充当回调。velaa5lx5#
单线法
或简化布局表达式,将代码移动到帮助器类
或使用绑定适配器