Android:在片段中实例化ViewModel时出现空指针异常

huangapple go评论69阅读模式
英文:

Android: NullPointerException When Instantiating ViewModel in Fragment

问题

我在尝试在 MyFragment 中实例化 MyViewModel 时遇到了 NullPointerException:

public class MyFragment extends Fragment {

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {

        myViewModel = new ViewModelProvider(this, new MyViewModelFactory(
                requireActivity().getApplication(), 0))
                .get(MyViewModel.class);
    }
}

堆栈跟踪似乎指向了最后一行 .get(MyViewModel.class);,我已经用 System.out.println()getApplication() 进行了空值检查,返回了一个值,所以我认为这不是问题所在。这种方法在我在活动中使用时运行得很好,但是当我尝试在片段中实现时,出现了 NullPointerException。我应该如何修改以使其工作?

以下是我的 ViewModelFactory 类的实现:

public class MyViewModelFactory implements ViewModelProvider.Factory {

    private Application application;
    private int intValue;

    public MyViewModelFactory(Application paramApplication, int paramIntValue) {
        application = paramApplication;
        intValue = paramIntValue;
    }

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        if (modelClass == MyViewModel.class) {
            return (T) new MyViewModel(application, intValue);
        }
        return null;
    }
}

我的 ViewModel 类:

public class MyViewModel extends AndroidViewModel {

    private MyDataModelRepository myDataModelRepository;
    private LiveData<List<MyDataModel>> liveDataListMyDataModel;

    public MyViewModel(@NonNull Application application, int intValue) {
        super(application);
        myDataModelRepository = new MyDataModelRepository(application);
        if (intValue > 0) {
            liveDataListMyDataModel = myDataModelRepository.getLiveDataListMyDataModelWhere(intValue);
        } else {
            liveDataListMyDataModel = myDataModelRepository.getLiveDataListMyDataModel();
        }
    }
}
英文:

I'm getting a NullPointerException when I tried to instantiate MyViewModel into MyFragment:

public class MyFragment extends Fragment {

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {

        myViewModel = new ViewModelProvider(this, new MyViewModelFactory(
                requireActivity().getApplication(), 0))
                .get(MyViewModel.class);
}

The stack trace seems to be pointing out the last line .get(MyViewModel.class); and I can't get it to work for days now. I did null checks on getApplication() by using System.out.println() and a value is returned, so I don't think that is the problem. This approach that I used worked just fine when I do this on an activity, but when I tried to implement this on a Fragment, a NullPointerException occured. What should I change to make this work?

Here's how I did my ViewModelFactory class:

public class MyViewModelFactory implements ViewModelProvider.Factory {

    private Application application;
    private int intValue;

    public MyViewModelFactory(Application paramApplication, int paramIntValue) {
        application = paramApplication;
        intValue = paramIntValue;
    }

    @NonNull
    @Override
    public &lt;T extends ViewModel&gt; T create(@NonNull Class&lt;T&gt; modelClass) {
        if (modelClass == MyViewModel.class) {
            return (T) new MyViewModel(application, intValue);
        }
        return null;
    }
}

My ViewModel class:

public class MyViewModel extends AndroidViewModel {

    private MyDataModelRepository myDataModelRepository;
    private LiveData&lt;List&lt;MyDataModel&gt;&gt; liveDataListMyDataModel;

    public MyViewModel(@NonNull Application application, int intValue) {
        super(application);
        myDataModelRepository= new myDataModelRepository(application);
        if (intValue&gt; 0) {
            liveDataListMyDataModel= myDataModelRepository.getLiveDataListMyDataModelWhere(intValue);
        } else {
            liveDataListMyDataModel= myDataModelRepository.getLiveDataListMyDataModel();
        }
    }
}

答案1

得分: 0

尝试使用以下代码来实例化 ViewModel

myViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(MyViewModel.class);

希望对您有所帮助。如有需要进一步解释,请随时提问。

英文:

Try using this to instantiate the ViewModel

myViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(MyViewModel.class);

Hope this helps. Feel free to ask for clarifications...

答案2

得分: 0

我刚刚重新调查了我的堆栈跟踪:

Caused by: java.lang.NullPointerException: 尝试在空对象引用上调用虚拟方法 'net.mypackage.DataModel.MyDataModel.MyDataModelDao net.mypackage.DataModel.MySystemDatabase.myDataModelDao()' 
        at net.mypackage.DataModel.MyDataModel.MyDataModelRepository.<init>(MyDataModelRepository.java:21)
        at net.mypackage.ViewModel.MyViewModel.MyViewModel.<init>(MyViewModel.java:21)
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
        at net.mypackage.View.MyFragment.onViewCreated(MyFragment.java:50)

并且发现错误很可能来自于我的 Repository 或者 Database Room 类,当我重新检查了 Database 类时:

public static synchronized MyDatabase getInstance(Context context) {
        if (myDatabase == null) {
            myDatabase = Room.databaseBuilder(context.getApplicationContext(),
                MyDatabase.class,
                "my_database")
                .fallbackToDestructiveMigration()
                .addCallback(roomCallback)
                .build();
        }
        return myDatabase;
    }

(myDatabase != null) 是我得到空指针异常的原因,代码中的指令是在构建数据库之前 myDatabase 必须不为 null,而由于这个实例在开始时为 null,它根本不会被构建,因此出现了空指针异常。

所以我将 (myDatabase != null) 改为 (myDatabase == null),问题得到了解决。

英文:

I just re-investigated my stack trace:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method &#39;net.mypackage.DataModel.MyDataModel.MyDataModelDao net.mypackage.DataModel.MySystemDatabase.myDataModelDao()&#39; on a null object reference
        at net.mypackage.DataModel.MyDataModel.MyDataModelRepository.&lt;init&gt;(MyDataModelRepository.java:21)
        at net.mypackage.ViewModel.MyViewModel.MyViewModel.&lt;init&gt;(MyViewModel.java:21)
	    at java.lang.reflect.Constructor.newInstance0(Native Method)&#160;
        at java.lang.reflect.Constructor.newInstance(Constructor.java:343)&#160;
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)&#160;
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)&#160;
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)&#160;
        at net.mypackage.View.MyFragment.onViewCreated(MyFragment.java:50)

And figured that my error is most likely coming from my Repository or my Database room class, and when I rechecked the Database class:

public static synchronized MyDatabase getInstance(Context context) {
        if (myDatabase != null) {
            myDatabase = Room.databaseBuilder(context.getApplicationContext(),
                myDatabase.class,
                &quot;my_database&quot;)
                .fallbackToDestructiveMigration()
                .addCallback(roomCallback)
                .build();
        }
        return myDatabase;
    }

The (myDatabase != null) is the reason why I'm getting NPE, the instruction in the code is that myDatabase has to be not null before building the database, and since this instance is null at the start, it will never be built at all, thus the NPE.

So I changed (myDatabase != null) to (myDatabase == null) and that solved it.

huangapple
  • 本文由 发表于 2020年7月26日 23:52:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/63102412.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定