Не может быть предоставлено без конструктора @Inject или с помощью аннотируемого метода @Provides- Dagger 2
Я использую 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);
1 ответ
Я решил проблему. Ошибка вызвана из-за неправильного объявления конструктора ViewModel. В моем коде я использую фабричный класс (TripViewModelFactory), чтобы использовать мой класс TripViewModel с конструктором, имеющим ненулевые аргументы, которые вводятся Dagger. Моя декларация конструктора класса TripViewModel была проблематичной, и конструктор, который я собираюсь вызвать с помощью фабричного класса, не был вызван. Таким образом, экземпляр ViewModel не создается, что вызвало ошибку, приведенную в моем вопросе по очереди.
Кроме того, если вы используете ту же структуру кода, которую я разделяю в вопросе, класс фрагмента, который создает экземпляр viewmodel из класса фабрики, должен реализовать интерфейс Injectable. Эта ошибка создала еще одну ошибку в моем коде, которой будет приятно поделиться.