我正在使用 Dagger 2,但出现了这个奇怪的错误,到目前为止对我来说似乎没有什么不对,但显然缺少了一些东西。任何帮助将不胜感激。
Error:(16, 8) error: [dagger.android.AndroidInjector.inject(T)] com.example.user.viewmodel.TripViewModel cannot be provided without an @Inject constructor or from an @Provides-annotated method. This type supports members injection but cannot be implicitly provided.
com.example.user.viewmodel.TripViewModel is injected at
com.example.user.di.ViewModelModule.bindTripViewModel(tripViewModel)
java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at
com.example.user.di.TripViewModelFactory.<init>(creators)
com.example.user.di.TripViewModelFactory is injected at
com.example.user.di.ViewModelModule.bindViewModelFactory(factory)
android.arch.lifecycle.ViewModelProvider.Factory is injected at
com.example.user.fragment.HomeFragment.viewModelFactory
com.example.user.fragment.HomeFragment is injected at
dagger.android.AndroidInjector.inject(arg0)
代码如下:
AppModule.java
@Module(includes = ViewModelModule.class)
class AppModule {
@Singleton
@Provides
MyRoomDatabase providesRoomDatabase(Application application) {
return Room.databaseBuilder(application,
MyRoomDatabase.class, "name_db").build();
}
@Singleton
@Provides
TripRepository provideTripRepository(TripDao tripDao){
return new TripRepository(tripDao);
}
@Singleton
@Provides
TripDao provideTripDao(MyRoomDatabase myRoomDatabase){
return myRoomDatabase.getTripDao();
}
}
ViewModelModule.java
@Module
public abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(TripViewModel.class)
abstract ViewModel bindTripViewModel(TripViewModel tripViewModel);
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(TripViewModelFactory factory);
}
MainActivityModule.java
@Module
public abstract class MainActivityModule {
@ContributesAndroidInjector(modules = FragmentBuildersModule.class)
abstract MainActivity contributeMainActivity();
}
FragmentBuildersModule.java
@Module
public abstract class FragmentBuildersModule {
@ContributesAndroidInjector
abstract HomeFragment contributeRepoFragment();
}
AppComponent.java
@Singleton
@Component(modules = {
AndroidInjectionModule.class,
AppModule.class,
MainActivityModule.class
})
public interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(Application application);
AppComponent build();
}
void inject(FuelApp fuelApp);
}
AppInjector.java
public class AppInjector {
private AppInjector() {}
public static void init(FuelApp fuelApp) {
DaggerAppComponent.builder().application(fuelApp)
.build().inject(fuelApp);
fuelApp.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
handleActivity(activity);
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
}
private static void handleActivity(Activity activity) {
if (activity instanceof HasSupportFragmentInjector) {
AndroidInjection.inject(activity);
}
if (activity instanceof FragmentActivity) {
((FragmentActivity) activity).getSupportFragmentManager()
.registerFragmentLifecycleCallbacks(
new FragmentManager.FragmentLifecycleCallbacks() {
@Override
public void onFragmentCreated(FragmentManager fm, Fragment f,
Bundle savedInstanceState) {
if (f instanceof Injectable) {
AndroidSupportInjection.inject(f);
}
}
}, true);
}
}
}
ViewModelKey.java
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
@interface ViewModelKey {
Class<? extends ViewModel> value();
}
TripViewModelFactory.java
@Singleton
public class TripViewModelFactory implements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;
@Inject
public TripViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
this.creators = creators;
}
@SuppressWarnings("unchecked")
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
Provider<? extends ViewModel> creator = creators.get(modelClass);
if (creator == null) {
for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : creators.entrySet()) {
if (modelClass.isAssignableFrom(entry.getKey())) {
creator = entry.getValue();
break;
}
}
}
if (creator == null) {
throw new IllegalArgumentException("unknown model class " + modelClass);
}
try {
return (T) creator.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
我已经寻找了很多解决方案,但尚未找到可行的解决方案。请随时分享任何评论。谢谢。
编辑:以下是我在 fragment 类中注入(inject) TripViewModel 的方法:
@Inject
ViewModelProvider.Factory viewModelFactory;
.
.
viewModel = ViewModelProviders.of(this, viewModelFactory).get(TripViewModel.class);
最佳答案
我已经解决了这个问题。该错误是由于错误的 ViewModel 构造函数声明引起的。在我的代码中,我使用工厂类 (TripViewModelFactory),以便将 TripViewModel 类与具有由 Dagger 注入(inject)的非零参数的构造函数一起使用。我的 TripViewModel 类构造函数声明有问题,并且未调用我打算由工厂类调用的构造函数。因此,未创建 ViewModel 实例,这又导致了我的问题中给出的错误。
此外,如果您使用我在问题中共享的相同代码结构,则从工厂类创建 viewmodel 实例的 fragment 类必须实现 Injectable 接口(interface)。这个错误在我的代码中造成了另一个错误,很高兴与大家分享。
关于java - 如果没有 @Inject 构造函数或 @Provides 注释的方法,则无法提供 - Dagger 2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48612377/