如果没有@Inject构造函数或@ Provide-annotated方法 - Dagger 2,则无法提供

时间:2018-02-04 19:55:22

标签: java android dagger-2 dagger

我正在使用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 个答案:

答案 0 :(得分:0)

我已经解决了这个问题。该错误是由于错误的ViewModel构造函数声明引起的。在我的代码中,我使用工厂类(TripViewModelFactory)来使用我的TripViewModel类,其构造函数具有由Dagger注入的非零参数。我的TripViewModel类构造函数声明是有问题的,并且我打算调用工厂类调用的构造函数。因此,不会创建一个ViewModel实例,该实例依次导致我的问题中给出的错误。

此外,如果您使用我在问题中共享的相同代码结构,则从工厂类创建viewmodel实例的fragment类必须实现Injectable接口。这个在我的代码中创建了另一个错误,这将很好地分享。