简体   繁体   English

如何使用 Dagger2 提供上下文

[英]How to provide Context with Dagger2

I am learning Android and I am following some guides for Retrofit2 with RxJava and Dagger2.我正在学习 Android,我正在遵循一些使用 RxJava 和 Dagger2 进行 Retrofit2 的指南。 Now I want to handle no internet connection case.现在我想处理没有互联网连接的情况。 I've found this answer , which seems to be elegant, but I do not understand how to apply it.我找到了这个答案,看起来很优雅,但我不明白如何应用它。

I've got some NetworkModule , with OkHttpClient provider.我有一些NetworkModule ,带有OkHttpClient提供程序。 I assume I need to create OkHttpClient.Builder with interceptor.我假设我需要使用拦截器创建OkHttpClient.Builder So it should look something like this: `所以它应该看起来像这样:`

@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();
}

This isn't working as I don't have Context .这不起作用,因为我没有Context In which direction should I go - to try to obtain context there, or maybe I misunderstand the concept of observables?我应该朝哪个方向走 - 尝试在那里获得上下文,或者我可能误解了可观察量的概念?

You can use the @Provides annotation in your DaggerModule to obtain application Context. 您可以在@Provides中使用@Provides批注来获取应用程序上下文。 Alternatively you can create a module which accepts a Context parameter in its constructor in case you need activity context. 或者,您可以创建一个模块,在您需要活动上下文的情况下,在其构造函数中接受Context参数。 Then you can build the component in your activity and inject the arguments into it. 然后,您可以在活动中构建组件并将参数注入其中。

 @Module
public class AppModule {

    private Context context;

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

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

}

Application class: 申请类:

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();
    }
}

Just wanted to supplement @anton-kazakov's answer, to provide a way to supply activity/service context in addition to application context:只是想补充@anton-kazakov 的回答,提供一种除了应用程序上下文之外还提供活动/服务上下文的方法:

ApplicationContext应用上下文

import javax.inject.Qualifier;

@Qualifier
public @interface ApplicationContext {
}

ServiceScope服务范围

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

import javax.inject.Scope;

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

ApplicationModule应用模块

@Module
public class ApplicationModule {

    private MyApplication mMyApplication;

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

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

ServiceModule (or, activity etc.) 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;
    }
}

ApplicationComponent应用组件

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);

}

ServiceComponent服务组件

import dagger.Subcomponent;

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

    void inject(MyService myService);

}

Application应用

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;
    }
}

Service服务

import javax.inject.Inject;

public class MyService extends Service {

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

References参考

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

Kotlin approach Kotlin 方法

You can provide the Application , which can be used to provide the `Context.您可以提供Application ,它可用于提供 `Context.

Define an AppComponent:定义一个 AppComponent:

import android.app.Application
import dagger.BindsInstance
import dagger.Component
import javax.inject.Singleton

@Component
@Singleton
interface AppComponent {
  @Component.Builder
  interface Builder {
    fun build(): AppComponent

    @BindsInstance
    fun application(application: Application): Builder
  }
}

Extend Application like so:像这样扩展应用程序:

abstract class MyApp : Application() {
    override fun onCreate() {
       super.onCreate()
       DaggerAppComponent.builder().application(this).build()
       // ..
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM