![](/img/trans.png)
[英]How to use same instance of ViewModel in activity as well as fragment?
[英]How to make sure I use the same instance of the ViewModel?
在 MainActivity 中,我使用以下方法创建了一个 ViewModel 对象:
class MainActivity : ComponentActivity() {
private val viewModel by viewModels<MainViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
if(viewModel.isActive()) {
//Do stuff...
} else {
//Do other stuff...
}
}
}
}
在可组合函数中,我使用 Hilt 将其注入:
@Composable
fun ActivateScreen(
viewModel: MainViewModel = hiltViewModel()
) {
Scaffold(
topBar = { /... },
content = {
UiContent(
onClick = {
viewModel.activate()
}
)
}
)
}
但在我看来,视图模型对象是不同的对象,因为当我单击激活时,更改不会传播到 MainActivity。 我需要重新启动应用程序才能看到更改。 如何确保我使用的是同一个实例? 任何帮助将不胜感激。
一种快速查看不相同的方法是在 viewmodel 的 init 块中放置一个断点,如果 mainactivity 内部的调用执行它并且可组合项内部的调用执行它,这将告诉您这两个实例是不同的。 如果您已经在活动中使用 hilt 创建视图模型,只需将其作为参数传递给您的可组合项
class MainActivity : ComponentActivity() {
private val viewModel by viewModels<MainViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
if(viewModel.isActive()) {
//Do stuff...
ActivateScreen(viewmodel)
} else {
//Do other stuff...
}
}
}
}
@Composable
fun ActivateScreen(
viewModel: MainViewModel
) {
Scaffold(
topBar = { /... },
content = {
UiContent(
onClick = {
viewModel.activate()
}
)
}
)
}
如果你想使用 Dagger Hilt 你应该这样做:(我在我的项目中也使用了类似的代码)
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@Inject
lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
if(viewModel.isActive()) {
//Do stuff...
ActivateScreen(viewmodel)
} else {
//Do other stuff...
}
}
}
}
@Composable
fun ActivateScreen(
viewModel: MainViewModel
) {
Scaffold(
topBar = { /... },
content = {
UiContent(
onClick = {
viewModel.activate()
}
)
}
)
}
@HiltAndroidApp
class MyApp: Application()
在 Manifest.xml 中
<application
android:name=".MyApp"
您没有看到更改传播到 Main 活动的原因可能不是由于 viewModel 的实例是 2 个不同实例的问题,但很可能是因为 Compose 没有触发重组,因为值已签入MainActivity
if(viewModel.isActive())
不是 Compose 知道的状态。 为了触发重组,您需要读取 compose 知道的状态。 实现此目的的一种方法是在 viewModel 中使用mutableStateOf
,而不是让isActive
成为一个函数,它可以是一个带有自定义 getter 的val
,或者您可以使用委托形式。
var isActive by mutableStateOf(false)
至于检查两者是否确实是同一个实例,如果你在每一个赋值后在代码中打断点,你就可以得到hashcode,除非你覆盖了hashCode
,否则它默认是对象的内存地址,如果两个实例具有相同的内存地址,那么它们几乎可以肯定是同一个实例。 另一种方法是传递它们,直到您可以使用===
进行引用比较而不是相等比较,这将判断它们是否是相同的实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.