【问题标题】:How to get an Instance of ViewModel in activity in 2020/21?如何在 2020/21 年获得活动中的 ViewModel 实例?
【发布时间】:2020-05-14 02:24:00
【问题描述】:

我是 mvvm 模式的新手。我为主要活动创建了一个 ViewModel。现在我想在主要活动中获取 ViewModel 的实例。

Stackoverflow 上的大多数教程和答案都建议使用 ViewModelProviders.of(...,但这已被弃用。

所以根据 stackoverflow 上的这个问题:ViewModelProviders is deprecated in 1.1.0 onCreate 中的主要活动,我执行以下操作(我可以发誓我已经让它运行了):mainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);

但是,我收到一条错误消息,告诉我没有找到合适的构造函数。

error: no suitable constructor found for ViewModelProvider(MainActivity)

另外,为了明确起见,MainActivity 应该是 ViewModelStoreOwner,我创建了一个变量 ViewModelStoreOwner vmso = this; 并将该变量放入构造函数中,如下所示: mainActivityViewModel = new ViewModelProvider(vmso).get(MainActivityViewModel.class);

【问题讨论】:

  • 您确定您对this 的引用正确吗?如果是片段,则需要使用getActivity() 而不是this iirc,如果您在侦听器或匿名类中,则必须使用MainActivity@this
  • 我在主Activity的onCreate()中调用方法
  • 不,它没有。 Java代码中描述的解决方案是boardViewModel = new ViewModelProvider(this).get(BoardViewModel.class),相当于我已经尝试过的mainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);,但似乎没有合适的构造函数。

标签: android mvvm viewmodel androidx viewmodelproviders


【解决方案1】:

根据Android 文档,您可以这样做:

科特林

implementation 'androidx.activity:activity-ktx:1.3.1'

val model: MyViewModel by viewModels()

JAVA

implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'

MyViewModel model = new ViewModelProvider(this).get(MyViewModel.class);
        

【讨论】:

    【解决方案2】:

    我遇到了类似的问题,最后发现我错过了类定义中的“extends ViewModel”,所以它应该是这样的:

    public class ViewModelClass extends ViewModel
    {
        // Tracks the score for Team A
        public int scoreTeamA = 0;
    
        // Tracks the score for Team B
        public int scoreTeamB = 0;
    }
    

    【讨论】:

      【解决方案3】:

      在活动中使用val viewModel by viewModels<TheViewModel>(),在片段中使用val viewModel by activityViewModels<TheViewModel>(),以从活动中获取相同的视图模型(因此共享视图模型)。

      现在这是androidx 的一部分

      【讨论】:

      • 谢谢!这对大多数人来说可能很明显,但您也可以使用val viewModel: ThisViewModel by viewModels()val viewModel: ThisViewModel by activityViewModels()
      【解决方案4】:

      以新方式获取 ViewModel

      MainActivityViewModel mainActivityViewModel;
          mainActivityViewModel= new ViewModelProvider(this).get(MainActivityViewModel.class);
      

      【讨论】:

      • 这是 Java。我们使用 Kotlin。
      【解决方案5】:

      在您的应用中使用Fragment-ktx libr,您可以获得如下视图模型

      首先将 Gradle 文件更新为应用程序 -> build.gradle

      implementation 'androidx.fragment:fragment-ktx:1.1.0'
      

      // 将 ActivityFragment 中的 ViewModel 获取为

      private val viewModel: MainActivityViewModel by viewModels()
      

      // 如果您想在 ChildFragment 中获得与

      相同的 ViewModel 实例
       private val viewModel: MainActivityViewModel by viewModels(
          ownerProducer = { requireParentFragment() }
      )
      

      【讨论】:

      • Fragment-ktx 用于片段。我们需要 activity-ktx
      【解决方案6】:

      您可以使用ViewModelFactory

      val viewModelFactory = VMFactory(requireActivity().application)
      viewModel= ViewModelProvider(requireActivity(),viewModelFactory).get(MainViewModel::class.java)
      

      VMFactory 代码:

      class VMFactory(application: Application) : ViewModelProvider.NewInstanceFactory() {
      
          val _application: Application=application
      
          @NonNull
          override fun <T : ViewModel?> create(@NonNull modelClass: Class<T>): T {
                  return  MainViewModel(_application) as T
          }
      }
      

      请注意,这里我的MainViewModel 扩展了AndroidViewModel,因此需要应用程序作为输入参数。

      【讨论】:

        【解决方案7】:

        您应该将您的 gradle 文件更新为:

        实现'androidx.lifecycle:lifecycle-extensions:2.2.0'

        由于这种变化,您可以将 Activity 传递给您提到的构造函数:

        mainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);
        

        【讨论】:

          【解决方案8】:

          目前,唯一对我有用的是使用: MainActivityViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MainActivityViewModel.class);

          但是,我仍然感谢任何建议,如何使用 new ViewModelProvider(this).get(MainActivityViewModel.class); 来实现不同的操作

          【讨论】:

          • 这仍然失败,但这次用java.lang.RuntimeException: Cannot create an instance of class xxx 代替
          • 你关注第一个答案了吗?
          【解决方案9】:

          Duplicate question and already answered here

          简单替换:

          这个:

          boardViewModel = ViewModelProviders.of(this).get(BoardViewModel::class.java)
          

          有了这个:

          boardViewModel = ViewModelProvider(this).get(BoardViewModel::class.java)
          

          【讨论】:

          • 如果这个问题是重复的,请不要回答并标记为这样
          • 另外,您的建议不起作用,但如问题中所述以error: no suitable constructor found for ViewModelProvider(MainActivity) 失败
          • 这里要注意的主要是我们需要替换的行是 ViewModelProvider 而不是 ViewModelProviders。注意最后的“s”。
          【解决方案10】:

          ViewModel viewModel = ViewModelProviders.of(this).get(ViewModel.class);

          Android 支持库版本已折旧。因此,您需要确保导入 Androidx。并且需要在 Gradle 文件中实现 androidx 依赖。

          不建议使用“new”关键字创建新的 ViewModel 对象。

          【讨论】:

          猜你喜欢
          • 2020-06-05
          • 2020-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多