Dagger2 ViewModel注入重构报错:缺少@Provides注解方法提供Map依赖
这个错误我之前重构项目时也踩过坑!本质就是Dagger找不到构建Map<Class<? extends ViewModel>, Provider<ViewModel>>的来源——这个Map是ViewModelFactory用来根据类名创建对应实例的核心依赖,重构时很容易不小心破坏了相关配置。下面是几个最常见的排查和修复方向:
1. 检查ViewModelModule的注解是否完整
重构时最容易遗漏或误改的就是@IntoMap和@ViewModelKey这些关键注解,或者搞错了Module的类型(比如把抽象类改成普通类,反之亦然)。
如果你的ViewModel本身带有@Inject构造函数,用@Binds绑定的Module应该是这样:
@Module public abstract class ViewModelModule { @Binds @IntoMap @ViewModelKey(HomeViewModel.class) abstract ViewModel bindHomeViewModel(HomeViewModel viewModel); // 其他ViewModel的绑定逻辑同理 }
如果ViewModel需要外部依赖、构造函数没有@Inject,则用@Provides提供实例:
@Module public class ViewModelModule { @Provides @IntoMap @ViewModelKey(HomeViewModel.class) ViewModel provideHomeViewModel(HomeRepository homeRepo) { return new HomeViewModel(homeRepo); } }
另外要确认你的自定义@ViewModelKey注解类没有被误删或修改:
@Qualifier @Retention(RetentionPolicy.RUNTIME) public @interface ViewModelKey { Class<? extends ViewModel> value(); }
2. 确认AppComponent正确包含了ViewModelModule
重构时如果调整了Component的依赖关系或Module的位置,很可能会把ViewModelModule从Component的modules列表里漏掉。检查你的AppComponent配置:
@Component(modules = { AndroidInjectionModule.class, ViewModelModule.class, // 必须确保这个Module在这里 ActivityBindingModule.class, // 其他必要的Module }) public interface AppComponent extends AndroidInjector<MyApp> { // ... }
3. 检查ViewModelFactory的注入配置
这个Map是通过ViewModelFactory的构造函数注入的,要确保Factory的构造函数带有@Inject注解,或者在Module里正确提供它:
public class ViewModelFactory implements ViewModelProvider.Factory { private final Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModelCreators; // 必须有@Inject,让Dagger自动注入这个Map @Inject public ViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModelCreators) { this.viewModelCreators = viewModelCreators; } @Override @NonNull public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { Provider<? extends ViewModel> creator = viewModelCreators.get(modelClass); if (creator == null) { throw new IllegalArgumentException("Unknown ViewModel class: " + modelClass); } try { return (T) creator.get(); } catch (Exception e) { throw new RuntimeException(e); } } }
同时,在需要使用ViewModel的Activity/Fragment里,要确保注入这个Factory,而非手动实例化:
public class HomeActivity extends AppCompatActivity { @Inject ViewModelFactory viewModelFactory; private HomeViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { AndroidInjection.inject(this); super.onCreate(savedInstanceState); viewModel = new ViewModelProvider(this, viewModelFactory).get(HomeViewModel.class); } }
4. 清理kapt缓存并重建项目
有时候重构后kapt生成的Stub文件(就是报错里提到的tmp/kapt3/stubs目录下的文件)会残留缓存,导致Dagger识别不到最新配置。执行以下操作:
- 在Android Studio里点击
Build -> Clean Project - 接着点击
Build -> Rebuild Project - 或者用命令行执行:
./gradlew clean build
以上几步排查下来,基本能解决这个问题。我当时就是重构时不小心把ViewModelModule从AppComponent的modules列表里删掉了,加回去再清理缓存就恢复正常了!
内容的提问来源于stack exchange,提问作者antanas_sepikas

