You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级AndroidX Lifecycle 2.2.0后,如何通过Fragment访问Activity的AndroidViewModel?

解决AndroidX Lifecycle 2.2.0+中Fragment访问Activity共享AndroidViewModel的问题

问题背景

你在重构Android应用时采用了Room、ViewModel、LiveData等架构组件,其中CanteensViewModel(继承自AndroidViewModel)需要被多个Fragment共享。原本在Activity和Fragment中通过ViewModelProvider获取实例的方式,在升级到androidx.lifecycle 2.2.0版本后失效,抛出了InstantiationException,提示你的ViewModel没有无参构造函数。

错误详情

报错的完整栈追踪如下:

2020-02-28 14:30:16.098 25279-25279/com.pasta.mensadd E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.pasta.mensadd, PID: 25279
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.pasta.mensadd/com.pasta.mensadd.ui.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.pasta.mensadd.ui.viewmodel.CanteensViewModel
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2795)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2873)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1602)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6543)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.RuntimeException: Cannot create an instance of class com.pasta.mensadd.ui.viewmodel.CanteensViewModel
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:221)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.pasta.mensadd.ui.MainActivity.onCreate(MainActivity.java:70)
at android.app.Activity.performCreate(Activity.java:7023)
at android.app.Activity.performCreate(Activity.java:7014)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2748)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2873)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1602)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6543)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.InstantiationException: java.lang.Class<com.pasta.mensadd.ui.viewmodel.CanteensViewModel> has no zero argument constructor
at java.lang.Class.newInstance(Native Method)
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:219)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.pasta.mensadd.ui.MainActivity.onCreate(MainActivity.java:70)
at android.app.Activity.performCreate(Activity.java:7023)
at android.app.Activity.performCreate(Activity.java:7014)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2748)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2873)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1602)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6543)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

核心原因

androidx.lifecycle 2.2.0版本后,ViewModelProvider的默认工厂改为了NewInstanceFactory,这个工厂只会尝试用无参构造函数创建ViewModel实例。而你的CanteensViewModel继承自AndroidViewModel,它需要接收Application参数完成初始化,直接使用默认工厂自然会抛出无参构造不存在的异常。

正确解决方案

你自己摸索出的方法是完全可行的,具体步骤如下:

  1. 在Activity中初始化ViewModel时指定AndroidViewModelFactory
    在MainActivity的onCreate方法中,使用带工厂参数的ViewModelProvider构造函数,确保用正确的工厂创建ViewModel并绑定到Activity生命周期:

    new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication()))
        .get(CanteensViewModel.class);
    
  2. 在Fragment中通过Activity作为所有者获取ViewModel
    在Fragment中,以requireActivity()作为ViewModelProvider的所有者参数,就能获取到Activity中创建的同一个ViewModel实例:

    new ViewModelProvider(requireActivity()).get(CanteensViewModel.class);
    

注意事项

  • 不要在每个Fragment中单独调用ViewModelProvider.AndroidViewModelFactory.getInstance(...).create(...)创建ViewModel,这样每个Fragment都会得到独立的实例,完全失去了共享ViewModel的意义。
  • 确保你的CanteensViewModel构造函数正确接收Application参数并传递给父类:
    public class CanteensViewModel extends AndroidViewModel {
        public CanteensViewModel(Application application) {
            super(application);
            // 初始化仓库等业务逻辑
        }
    }
    

内容的提问来源于stack exchange,提问作者julianctni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 19:27:43