简体   繁体   English

如何确保我使用相同的 ViewModel 实例?

[英]How to make sure I use the same instance of the ViewModel?

In the MainActivity I create a ViewModel object using:在 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...
            }
        }
    }
}

And inside a composable function, I'm injecting it using Hilt:在可组合函数中,我使用 Hilt 将其注入:

@Composable
fun ActivateScreen(
    viewModel: MainViewModel = hiltViewModel()
) {
    Scaffold(
        topBar = { /... },
        content = {
            UiContent(
                onClick = {
                    viewModel.activate()
                }
            )
        }
    )
}

But it seems to me that the view model objects are different objects, because when I click activate, the change is not propagated to the MainActivity.但在我看来,视图模型对象是不同的对象,因为当我单击激活时,更改不会传播到 MainActivity。 I need to restart the app in order to see the change.我需要重新启动应用程序才能看到更改。 How to make sure I'm using the same instance?如何确保我使用的是同一个实例? Any help would be greatly appreciated.任何帮助将不胜感激。

A quick way to see that is not the same is to place a breakpoint in the init block of the viewmodel, if the call inside mainactivity executes it and the call inside your composable does it, that will tell you that the two instances are different.一种快速查看不相同的方法是在 viewmodel 的 init 块中放置一个断点,如果 mainactivity 内部的调用执行它并且可组合项内部的调用执行它,这将告诉您这两个实例是不同的。 If you are already creating the viewmodel in your activity with hilt, just pass it as a parameter to your composable如果您已经在活动中使用 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()
                }
            )
        }
    )
}

If you want to use Dagger Hilt you should do like this: (I also used a similar code in my project)如果你想使用 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()

And in Manifest.xml在 Manifest.xml 中

<application
    android:name=".MyApp"

The reason why you are not seeing the change propagated to Main activity is perhaps not due to an issue of the instances of the viewModel being 2 different instances, but more than likely it is because Compose isn't triggering a recomposition because the value checked in MainActivity if(viewModel.isActive()) is not a state that Compose is aware of.您没有看到更改传播到 Main 活动的原因可能不是由于 viewModel 的实例是 2 个不同实例的问题,但很可能是因为 Compose 没有触发重组,因为值已签入MainActivity if(viewModel.isActive())不是 Compose 知道的状态。 In order for the recomposition to trigger, you will need to read a state that compose is aware of.为了触发重组,您需要读取 compose 知道的状态。 One way to achieve this is to use mutableStateOf in the viewModel, then rather than having isActive be a function, it can be a val with a custom getter, or you can use the delegate form.实现此目的的一种方法是在 viewModel 中使用mutableStateOf ,而不是让isActive成为一个函数,它可以是一个带有自定义 getter 的val ,或者您可以使用委托形式。

var isActive by mutableStateOf(false)

As for checking if the two are indeed the same instance, if you place a breakpoint in the code after each one is assigned, you can get the hashcode, which unless you've overridden hashCode it will default to be the memory address of the object, if both instances have the same memory address, they are the almost certainly the same instance.至于检查两者是否确实是同一个实例,如果你在每一个赋值后在代码中打断点,你就可以得到hashcode,除非你覆盖了hashCode ,否则它默认是对象的内存地址,如果两个实例具有相同的内存地址,那么它们几乎可以肯定是同一个实例。 Another way would be to pass them around until you can use === to do a reference comparison rather than a equality comparison, which will tell if they are the same instance or not.另一种方法是传递它们,直到您可以使用===进行引用比较而不是相等比较,这将判断它们是否是相同的实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在活动和片段中使用相同的 ViewModel 实例? - How to use same instance of ViewModel in activity as well as fragment? 如何使用共享的 ViewModel,并避免每次与导航组件重用相同的实例 - How to use a shared ViewModel, and avoid reusing the same instance of it every time with Navigation Component 如何确保Android Beam无法启动我的&#39;singleTop&#39;活动的新实例? - How can I make sure Android Beam doesn't start a new instance of my 'singleTop' activity? 如果我需要将上下文传递给 ViewModel,如何将 viewModel 实例分配给片段内的绑定 viewModel 数据变量? - How to assign viewModel instance to binding viewModel data variable within fragment, if i need to pass context to ViewModel? 努力获得相同的ViewModel实例 - Struggle to get the same ViewModel instance 如何为父片段和子片段提供相同的 ViewModel 实例 - How to give same instance of ViewModel to both the Parent and Child fragment 如何使用 Koin DI 在活动之间共享相同的 ViewModel 实例? - How to share same instance of ViewModel between Activities using Koin DI? 如何确保不会同时选中多个复选框? 在科特林 - How can I make sure that more than one checkbox is not selected at the same time? in kotlin 如何确保无需计时器即可在Android应用程序中使用Azure移动服务? - How do I make sure I can use Azure Mobile Services in my Android app without a Timer? 如何使用rxjava在存储库中提出改造请求,并使用LiveData将其传递给ViewModel? - How do i use rxjava to make a retrofit request in a repository and pass it to a ViewModel using LiveData?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM