无法提供Dagger改造

时间:2018-03-10 11:22:14

标签: android dependency-injection retrofit2 dagger-2

Admiteddly,Dagger非常强硬,我正试图注入Retrofit。我注入了Context和SharedPreferences,它运行正常。但是Retrofit打破了这一切。 它识别DaggerRetrofitComponent类,但没有找到DaggerAppComponent。

改造模块:

@Module
public class RetrofitModule {
    public static final String BASE_URL = "http://api.themoviedb.org/3/";
    @Provides
    HttpLoggingInterceptor getHttpLoggingInterceptor(){
        return new HttpLoggingInterceptor();

    }
    @Provides
    OkHttpClient getOkHttpClient(HttpLoggingInterceptor interceptor){
        return new OkHttpClient.Builder().addInterceptor(interceptor).build();
    }
    @Provides
    GsonConverterFactory getGsonConverterFactory(){
        return GsonConverterFactory.create();
    }
    @Provides
    Retrofit getRetrofit(GsonConverterFactory gsonConverterFactory, OkHttpClient client){
        return new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(gsonConverterFactory)
                .client(client).build();
    }
}

应用:

public class MyApplication extends Application {
    private static AppComponent appComponent;
    public static AppComponent getAppComponent(){
        return appComponent;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        appComponent=buildComponent();

    }


    protected AppComponent buildComponent(){
        if(BuildConfig.DEBUG){
            Timber.plant(new Timber.DebugTree());
        }

        return DaggerAppComponent.builder().sharedPreferenceModule(new SharedPreferenceModule()).contextModule(new ContextModule(this)).build();


    }
}

AppComponent:

@Singleton
@Component(modules = {ContextModule.class, SharedPreferenceModule.class})
public interface AppComponent {
    void inject(MainActivity mainActivity);
}

RetrofitComponent:

@Singleton
@Component(modules = {RetrofitModule.class})
public interface RetrofitComponent {
    void injectRetrofit(Activity activity);
//
}

MainActivity:

public class MainActivity extends AppCompatActivity {
    @Inject
    Context context;
    @Inject
    SharedPreferences sharedPreferences;
    @Inject
    Retrofit retrofit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerRetrofitComponent.builder().retrofitModule(new RetrofitModule()).build().injectRetrofit(this);
        MyApplication.getAppComponent().inject(this);


    }
}

3 个答案:

答案 0 :(得分:1)

删除此课程:

//@Singleton
//@Component(modules = {RetrofitModule.class})
//public interface RetrofitComponent {
//    void injectRetrofit(Activity activity);
//
//}

并修改AppComponent

@Singleton
@Component(modules = {ContextModule.class, SharedPreferenceModule.class, RetrofitModule.class})
public interface AppComponent {
    void inject(MainActivity mainActivity);
}

答案 1 :(得分:0)

Dagger 2不允许从多个组件注入依赖项。您应该考虑使用子组件。

https://google.github.io/dagger/subcomponents.html

UPD:我建议您从AppComponent创建子组件,例如NetComponent。然后在您的活动中提供getNetComponent.inject()。由于NetComponent将从AppComponent中获取,因此它将提供您需要的appComponent的所有依赖项

它有点复杂,但它是一种正确的方法,你也应该了解Dagger Scopes。

OR

快速的方法只是将您的网络依赖项放入AppComponent。

答案 2 :(得分:0)

我不确定为什么要将Retrofit作为组件(应用程序组件中的模块应该足够),然后您应该使用最后一个Dagger版本来处理控制器视图(活动和片段)的自动注入

@Singleton
@Component(modules = [ApplicationModule::class])
interface ApplicationComponent : AndroidInjector<MyApplication>
{
    override fun inject(application: MyApplication)

    @Component.Builder
    interface Builder
    {
        @BindsInstance
        fun application(application: MyApplication): Builder

        fun build(): ApplicationComponent
    }
}

__

@Module(includes = [AndroidSupportInjectionModule::class,ActivityBuilderModule::class, NetworkModule::class])
abstract class ApplicationModule
{
    @Binds
    @Singleton
    abstract fun bindApplication(application: MyApplication): Application

    @Module
    companion object
    {
        @Provides
        @Singleton
        @ApplicationContext
        @JvmStatic
        fun provideApplicationContext(application: MyApplication): Context = application
    }
}

__

@Module
abstract class ActivityBuilderModule
{
    @ContributesAndroidInjector(modules = [MainActivityModule::class])
    @ActivityScope
    abstract fun contributeMainActivity(): MainActivity

    //others activities there
}

@Module
object NetworkModule
{
    // For simplicity just retrofit provider, but all others network resources should be here of course

    @Provides
    @Singleton
    @JvmStatic
    fun provideRetrofit(rxJava2CallAdapterFactory: RxJava2CallAdapterFactory,
                        nullOrEmptyConverterFactory: Converter.Factory,
                        @ApplicationContext okHttpClient: OkHttpClient,
                        gsonConverterFactory: GsonConverterFactory): Retrofit =
        Retrofit.Builder()
            .addCallAdapterFactory(rxJava2CallAdapterFactory)
            .addConverterFactory(nullOrEmptyConverterFactory)
            .addConverterFactory(gsonConverterFactory)
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .build()
}

__

class MyApplication : DaggerApplication()
{
    private val applicationInjector = DaggerApplicationComponent.builder()
        .application(this)
        .build()

    public override fun applicationInjector() = applicationInjector
}

__

然后从你的活动/片段中继承DaggerActivity或DaggerFragment,你应该能够开箱即用

您可以查看我的模板项目https://github.com/SamYStudiO/beaver,它可能会有所帮助。

ps:对不起,所有kotlin都应该很容易转换为java