【问题标题】:jetpack compose pass parameter to viewModeljetpack compose 将参数传递给 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.
    }
}

【问题讨论】:

    标签: android kotlin android-viewmodel android-jetpack-compose


    【解决方案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 DataStorenot 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 */
      }
      

      【讨论】:

        猜你喜欢
        • 2022-01-21
        • 1970-01-01
        • 1970-01-01
        • 2022-09-25
        • 1970-01-01
        • 2021-06-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多