如何使用Dagger2提供Context

时间:2017-04-28 15:43:29

标签: android rx-java retrofit2 okhttp dagger-2

我正在学习Android,我正在使用RxJava和Dagger2来关注Retrofit2的一些指南。 现在我想处理没有互联网连接的情况。 我发现了这个answer 似乎很优雅,但我不明白如何应用它。

我有一些NetworkModuleOkHttpClient提供商。 我假设我需要使用拦截器创建OkHttpClient.Builder。所以看起来应该是这样的:`

@Provides
@Singleton
OkHttpClient provideOkHttpClient(Cache cache) {
    ConnectivityInterceptor ci = new ConnectivityInterceptor(networkObservable()));
    OkHttpClient.Builder.addInterceptor(ci)
    return builder.build();
}

private boolean networkObservable() {
    ConnectivityManager cm =
            (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}

这不起作用,因为我没有Context。 我应该去哪个方向 - 试图在那里获得背景,或者我可能误解了可观测量的概念?

2 个答案:

答案 0 :(得分:5)

您可以在DaggerModule中使用@Provides注释来获取应用程序上下文。或者,您可以创建一个模块,在您需要活动上下文的情况下,在其构造函数中接受Context参数。然后,您可以在活动中构建组件并将参数注入其中。

 @Module
public class AppModule {

    private Context context;

    public AppModule(@NonNull Context context) {
        this.context = context;
    }

    @Singleton
    @Provides
    @NonNull
    public Context provideContext(){
        return context;
    }

}

申请类:

public class PFApplication extends Application {

    private static AppComponent appComponent;

    public static AppComponent getAppComponent() {
        return appComponent;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        appComponent = buildComponent();
    }

    public AppComponent buildComponent(){
        return DaggerAppComponent.builder()
                .appModule(new AppModule(this))
                .build();
    }
}

答案 1 :(得分:1)

只是想补充@anton-kazakov的回答,提供一种除了应用程序上下文之外还提供活动/服务上下文的方法:

应用上下文

import javax.inject.Qualifier;

@Qualifier
public @interface ApplicationContext {
}

服务范围

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import javax.inject.Scope;

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ServiceScope {
}

应用模块

@Module
public class ApplicationModule {

    private MyApplication mMyApplication;

    public ApplicationModule(@NonNull MyApplication myApplication) {
        mMyApplication = myApplication;
    }

    @Singleton
    @Provides
    @NonNull
    @ApplicationContext
    public Context provideApplicationContext() {
        return mMyApplication;
    }
}

ServiceModule(或活动等)

import dagger.Module;
import dagger.Provides;

@Module
public class ServiceModule {

    private final MyService mMyService;

    public ServiceModule(MyService myService) {
        mMyService = myService;
    }

    @ServiceScope
    @Provides
    public Context provideContext() {
        return mMyService;
    }
}

应用组件

import javax.inject.Singleton;

import dagger.Component;

@Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {

    ServiceComponent newMyServiceComponent(ServiceModule serviceModule);

    // This is optional, just putting here to show one possibility
    void inject(BootCompleteReceiver bootCompleteReceiver);

}

服务组件

import dagger.Subcomponent;

@ServiceScope
@Subcomponent(modules = {ServiceModule.class})
public interface ServiceComponent {

    void inject(MyService myService);

}

申请

public class MyApplication extends Application {

    private ApplicationComponent mApplicationComponent;

    @Override
    public void onCreate() {
        // mApplicationComponent = DaggerApplicationModule.builder()
        //         .applicationModule(new ApplicationModule(this))
        //         .build();
        super.onCreate();
    }

    /**
     * Note: {@link ContentProvider#onCreate} is called before 
     * {@link Application#onCreate}, hence if you have a 
     * {@link ContentProvider}, inject here instead of 
     * in {@link Application#onCreate}.
     * <p>
     * https://stackoverflow.com/a/44413873
     * <p>
     * https://stackoverflow.com/questions/9873669/how-do-i-catch-content-provider-initialize
     *
     * @param base The base Context.
     */
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        mApplicationComponent = DaggerApplicationComponent.builder()
                .applicationModule(new ApplicationModule(this))
                .build();
    }

    public ApplicationComponent getApplicationComponent() {
        return mApplicationComponent;
    }
}

服务

import javax.inject.Inject;

public class MyService extends Service {

    @Override
    public void onCreate() {
        ((MyApplication) getApplicationContext())
                .getApplicationComponent()
                .newMyServiceComponent(new ServiceModule(this))
                .inject(this);
        super.onCreate();
    }
}

参考资料

https://dagger.dev/api/2.19/dagger/Component.html https://dagger.dev/api/2.19/dagger/Module.html#subcomponents--