jetpack compose 将参数传递给 viewModel
Posted
技术标签:
【中文标题】jetpack compose 将参数传递给 viewModel【英文标题】:jetpack compose pass parameter to viewModel 【发布时间】:2021-08-31 01:36:21 【问题描述】:我们如何在jetpack compose中将参数传递给viewModel?
这是我的组合
@Composable
fun UsersList()
val myViewModel: MyViewModel = viewModel("db2name") // pass param like this
这是视图模型
class MyViewModel(private val dbname) : ViewModel()
private val users: MutableLiveData<List<User>> by lazy
MutableLiveData<List<User>>().also
loadUsers()
fun getUsers(): LiveData<List<User>>
return users
private fun loadUsers()
// Do an asynchronous operation to fetch users.
【问题讨论】:
【参考方案1】:您需要创建一个工厂来将动态参数传递给 ViewModel,如下所示:
class MyViewModelFactory(private val dbname: String) :
ViewModelProvider.NewInstanceFactory()
override fun <T : ViewModel?> create(modelClass: Class<T>): T = MyViewModel(dbname) as T
然后在可组合函数中像这样使用您的工厂:
@Composable
fun UsersList()
val myViewModel: MyViewModel =
viewModel(factory = MyViewModelFactory("db2name")) // pass param like this
现在您可以访问 ViewModel 中的 dbname 参数了:
class MyViewModel(private val dbname) : ViewModel()
// ...rest of the viewModel logics here
【讨论】:
为什么这没有在 android 网站上记录? 这实际上很难找到。如果您使用DataStore
Preferences 代码实验室,其中有两个,其中一个(Working with Preferences DataStore,not Preferences DataStore ) 有一个最终解决方案,它确实利用此实现将UserRespository
类与ViewModel
绑定,但codelab 本身并没有教你任何关于它的内容并且充满差异(codelab 不是回购)。我想我们应该从 Android View 方面了解这一点,因为它在 View 系统中强烈建议始终使用 ViewModelProvider
来管理 ViewModel 实例。【参考方案2】:
通常情况下,您不需要这样做。在 android MVVM 中,视图模型通过依赖注入从存储库中获取数据。
这里是推荐的android架构的官方文档:https://developer.android.com/jetpack/guide#recommended-app-arch
【讨论】:
这实际上很棒,但我认为这对于任何小型应用程序来说也是一种过载。我相信做这个问题的一个常见案例是任何小型应用程序。我认为它只会使初学者从大量的理解中抽象出来,从而使他们免于理解如何管理一小组依赖项等。但是,我确实 100% 同意这是任何中等规模的方法应用程序,或者当您决定自己在用于任何事情的一体式模板中实现此架构时;在这种情况下也适用于小型应用程序。【参考方案3】:正如@Secret Keeper 所说,您需要创建工厂。
如果您的 ViewModel 有依赖项, viewModel() 需要一个可选的 ViewModelProvider.Factory 作为参数。
class MyViewModelFactory(
private val dbname: String
) : ViewModelProvider.Factory
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T
if (modelClass.isAssignableFrom(MyViewModel::class.java))
return MyViewModel(dbname) as T
throw IllegalArgumentException("Unknown ViewModel class")
要创建您的 viewModel,您将传递可选参数。在您的 Composable 中,您可以执行以下操作。
val viewModel: MyViewModel = viewModel(
factory = MyViewModelFactory(
dbname = "myDbName"
)
【讨论】:
【参考方案4】:这里有一些 Jetpack Compose/Kotlin 特定的语法来实现相同的:
ui/settings/SettingsViewModel.kt
class SettingsViewModel(
private val settingsRepository: SettingsRepository
) : ViewModel()
/* Your implementation */
class SettingsViewModelFactory(
private val settingsRepository: SettingsRepository
) : ViewModelProvider.Factory
override fun <T : ViewModel> create( modelClass: Class<T> ): T
if( modelClass.isAssignableFrom( SettingsViewModel::class.java ) )
@Suppress( "UNCHECKED_CAST" )
return SettingsViewModel( settingsRepository ) as T
throw IllegalArgumentException( "Unknown ViewModel Class" )
然后:
MainActivity.kt
/* dataStore by preferencesDataStore */
class MainActivity : ComponentActivity()
private lateinit var settingsRepository: SettingsRepository
// Here we instantiate our ViewModel leveraging delegates and
// a trailing lambda
private val settingsViewModel by viewModels<SettingsViewModel>
SettingsViewModelFactory(
settingsRepository
)
/* onCreate -> setContent -> etc */
【讨论】:
以上是关于jetpack compose 将参数传递给 viewModel的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin jetpack compose Tab的渲染 AnimatedVisibility的使用
如何将 POST 参数传递给 Durable Function,然后将此参数传递给 Timer Triggered 函数