我正在使用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);
}
}
}
我已经搜索了很多解决方案,但还没有提供有效的解决方案。请随时分享任何评论。感谢。
编辑:下面是我在片段类中注入TripViewModel的方法:
@Inject
ViewModelProvider.Factory viewModelFactory;
.
.
viewModel = ViewModelProviders.of(this, viewModelFactory).get(TripViewModel.class);
答案 0 :(得分:0)
我已经解决了这个问题。该错误是由于错误的ViewModel构造函数声明引起的。在我的代码中,我使用工厂类(TripViewModelFactory)来使用我的TripViewModel类,其构造函数具有由Dagger注入的非零参数。我的TripViewModel类构造函数声明是有问题的,并且我打算调用工厂类调用的构造函数。因此,不会创建一个ViewModel实例,该实例依次导致我的问题中给出的错误。
此外,如果您使用我在问题中共享的相同代码结构,则从工厂类创建viewmodel实例的fragment类必须实现Injectable接口。这个在我的代码中创建了另一个错误,这将很好地分享。