繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM