Java Android MVVM开发出现无法创建ViewModel实例的错误
Android MVVM 下"无法创建ViewModel实例"报错的Java版解决方案
问题背景
开发者跟随教程使用Java实现MVVM架构的Android应用时,运行触发“无法创建ViewModel实例”的崩溃。由于同类问题的解答均为Kotlin编写,开发者不了解Kotlin语法也无法对应理解实现逻辑,因此单独寻求可直接参考的Java版本解决思路。
开发者已实现的相关代码如下:
MainActivity 实现
UserViewModel userViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); userViewModel = new ViewModelProvider(this).get(UserViewModel.class); userViewModel.getAllUsers().observe(this, new Observer<List<User>>() { @Override public void onChanged(List<User> users) { //update recyclerview here Toast.makeText(MainActivity.this,"onChanged",Toast.LENGTH_LONG).show(); } }); }
UserViewModel 实现
public class UserViewModel extends AndroidViewModel { private UserRepository repository; private LiveData<List<User>> allUsers; public UserViewModel(@NonNull Application application) { super(application); repository = new UserRepository(application); allUsers = repository.getAllUsers(); } public void insert(User user) { repository.insert(user); } public LiveData<List<User>> getAllUsers() { return allUsers; } }
UserRepository 实现
public class UserRepository { private UserDao userDao; private LiveData<List<User>> allUsers; public UserRepository(Application application) { UserDatabase database = UserDatabase.getInstance(application); userDao = database.userDao(); allUsers = userDao.getAllUsers(); } public void insert(User user) { new Thread(new InsertInBackground(userDao,user)).start(); } public LiveData<List<User>> getAllUsers() { return allUsers; } private static class InsertInBackground implements Runnable { private UserDao userDao; private User user; public InsertInBackground(UserDao userDao, User user) { this.userDao = userDao; this.user = user; } @Override public void run() { userDao.insert(user); } } }
报错根因
直接调用new ViewModelProvider(this)时,系统会使用内置的默认构造工厂,这个工厂仅支持反射创建无参构造的ViewModel实例。
而当前实现的UserViewModel继承了AndroidViewModel,构造方法需要传入Application类型参数,默认工厂无法提供这个参数,反射创建实例时就会抛出“无法创建ViewModel实例”的运行时错误。
修正方案(纯Java实现,无Kotlin依赖)
将MainActivity中初始化ViewModel的代码,替换为系统提供的AndroidViewModelFactory工厂实例即可——这个工厂已经内置了Application实例的获取逻辑,完全匹配你当前的ViewModel构造方法要求:
把原来的初始化代码:
userViewModel = new ViewModelProvider(this).get(UserViewModel.class);
替换为:
userViewModel = new ViewModelProvider( this, ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication()) ).get(UserViewModel.class);
额外注意事项
- 确保项目引入的是AndroidX生命周期依赖,不要使用过时的
android.arch.lifecycle旧依赖,否则可能出现类找不到的问题 - 不需要自定义工厂类,上述系统提供的工厂已经可以覆盖所有继承
AndroidViewModel的类的创建逻辑 - 如果后续需要给ViewModel传入自定义的额外参数,再按需继承
ViewModelProvider.Factory实现自定义工厂即可,当前场景下不需要额外编码
内容的提问来源于stack exchange,提问作者M.Ahmed
相关产品推荐
相关产品推荐

