MVVM架构下自定义ViewModelFactory无法创建实例错误(Dagger2)
解决"无法创建CakeViewModel实例"的问题
嘿,我帮你找出了两个关键问题,正是它们导致了这个报错:
问题1:ViewModel Factory中的类型判断逻辑错误
看你的CakeViewModelFactory的create方法,你在判断modelClass.isAssignableFrom(Model.class),但你要创建的实例是CakeViewModel啊!这个判断完全错位了,系统会 fallback 到默认的ViewModel工厂,但你的CakeViewModel只有带参数的构造函数,默认工厂根本无法创建它,直接触发报错。
修改后的CakeViewModelFactory代码:
public class CakeViewModelFactory implements ViewModelProvider.Factory{ private final Model model; private final Application application; @Inject public CakeViewModelFactory(Model model, Application application) { this.model = model; this.application = application; } @NonNull @Override public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { // 这里要判断的是目标ViewModel类,不是Model! if (modelClass.isAssignableFrom(CakeViewModel.class)) { return (T) new CakeViewModel(model, application); } throw new IllegalArgumentException("Unknown ViewModel class"); } }
问题2:Activity中初始化ViewModel和Dagger注入的顺序颠倒了
在CakesActivity的onCreate方法里,你先调用了ViewModelProviders.of(this, factory).get(CakeViewModel.class),但这时候factory还没被Dagger注入,还是null!系统只能用默认的AndroidViewModelFactory尝试创建,而你的CakeViewModel没有无参构造函数,直接触发创建失败。
你需要先完成Dagger注入,再获取ViewModel,修改后的onCreate代码:
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_cakes); // 第一步:先执行Dagger注入,让factory被初始化 DaggerCakeComponent.builder() .cakeModule(new CakeModule(this)) .applicationComponent(CakeApplication.get(this).getComponent()) .build().inject(this); ButterKnife.bind(this); initializeList(); // 第二步:注入完成后,再用初始化好的factory获取ViewModel CakeViewModel viewModel = ViewModelProviders.of(this, factory).get(CakeViewModel.class); observeViewModel(viewModel); }
额外小建议
既然你已经引入了RxJava2,其实可以优化Model层的代码,把Retrofit的Call转换成Observable,再结合LiveDataReactiveStreams生成LiveData,这样代码更简洁,也能更好地利用RxJava的线程调度能力:
public LiveData<CakeResponse> getCakeList(){ return LiveDataReactiveStreams.fromPublisher( networkService.getTheCakes() // 先把Retrofit接口改成返回Observable<CakeResponse> .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .toFlowable(BackpressureStrategy.LATEST) ); }
按照上面的修改,你的创建实例错误应该就能解决了!
内容的提问来源于stack exchange,提问作者Athena
相关产品推荐
相关产品推荐

