Java Android报错:无法创建NoteViewModel类实例
问题描述
开发Java语言实现的Android笔记应用时,持续触发运行时崩溃,核心错误提示为Cannot create an instance of class com.aashushaikh.notesjava.viewModel.NoteViewModel。已尝试StackOverflow同类问题的多种解决方案均未生效:
- 调用
ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())方法初始化ViewModel - 自定义ViewModelFactory完成ViewModel实例化
- 相同业务逻辑用Kotlin实现可正常运行,仅Java版本触发崩溃
崩溃堆栈日志
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.aashushaikh.notesjava, PID: 22110 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.aashushaikh.notesjava/com.aashushaikh.notesjava.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.aashushaikh.notesjava.viewModel.NoteViewModel at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) Caused by: java.lang.RuntimeException: Cannot create an instance of class com.aashushaikh.notesjava.viewModel.NoteViewModel at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:269) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) at com.aashushaikh.notesjava.MainActivity.onCreate(MainActivity.java:42) at android.app.Activity.performCreate(Activity.java:6679) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) Caused by: java.lang.NoSuchMethodException: <init> [class android.app.Application] at java.lang.Class.getConstructor0(Class.java:2204) at java.lang.Class.getConstructor(Class.java:1683) 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 com.aashushaikh.notesjava.MainActivity.onCreate(MainActivity.java:42) at android.app.Activity.performCreate(Activity.java:6679) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
问题根因
从堆栈最底层的报错java.lang.NoSuchMethodException: <init> [class android.app.Application]可以直接定位核心问题:
默认的AndroidViewModelFactory通过反射创建ViewModel实例时,只会查找仅接收单个Application类型参数的构造方法,但当前NoteViewModel的构造方法额外定义了一个无用的String类型参数mParam,工厂找不到匹配的构造方法,直接抛出实例化失败异常。
另外代码中还存在一个隐藏空指针风险:NoteRepository类中allNotes的初始化写在构造方法外,执行时noteDao还未完成赋值,会触发空指针。
修复方案
- 修正
NoteViewModel构造方法,删除多余的无用String参数,保留符合AndroidViewModel实例化规则的单Application参数构造方法,修正后代码如下:
public class NoteViewModel extends AndroidViewModel { private NoteRepository noteRepository; public LiveData<List<Note>> allNotes; public NoteViewModel(@NonNull Application application) { super(application); NoteDao dao = NoteDatabase.getInstance(application).getNoteDao(); noteRepository = new NoteRepository(dao); allNotes = noteRepository.getAllNotes(); } public void deleteNote(Note note){ noteRepository.delete(note); } public void insertNote(Note note){ noteRepository.insert(note); } public LiveData<List<Note>> getAllNotes(){ return allNotes; } }
- 修复
NoteRepository的空指针隐患,将allNotes的初始化逻辑移到构造方法内部,保证noteDao完成赋值后再调用其方法,修正后代码如下:
public class NoteRepository { NoteDao noteDao; public LiveData<List<Note>> allNotes; public NoteRepository(NoteDao noteDao) { this.noteDao = noteDao; allNotes = noteDao.getAllNotes(); } public void insert(Note note){ new InsertNoteAsyncTask(noteDao).execute(note); } public void delete(Note note) { new DeleteNoteAsyncTask(noteDao).execute(note); } public LiveData<List<Note>> getAllNotes(){ return allNotes; } private static class InsertNoteAsyncTask extends AsyncTask<Note, Void, Void> { private NoteDao noteDao; private InsertNoteAsyncTask(NoteDao noteDao) { this.noteDao = noteDao; } @Override protected Void doInBackground(Note...notes) { noteDao.insert(notes[0]); return null; } } private static class DeleteNoteAsyncTask extends AsyncTask<Note, Void, Void> { private NoteDao noteDao; private DeleteNoteAsyncTask(NoteDao noteDao) { this.noteDao = noteDao; } @Override protected Void doInBackground(Note...notes) { noteDao.delete(notes[0]); return null; } } }
MainActivity中现有ViewModel初始化逻辑无需修改,保持原有写法即可正常运行:
viewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())).get(NoteViewModel.class);
补充:只有需要给ViewModel传入自定义额外参数时,才需要实现自定义ViewModelFactory,当前场景无额外参数需求,使用默认工厂即可。
内容的提问来源于stack exchange,提问作者Aashu Shaikh
相关产品推荐
相关产品推荐

