首页 > 解决方案 > Dagger2 - 将对象传递给模块的最佳实践?

问题描述

我正在尝试创建一个RetrofitModule. 我有一个interceptor使用AuthHeader对象添加动态标题的方法。我不确定如何将此对象传递给模块类。

@Module
public class RetrofitModule {

    private static final String TAG = "RetrofitModule";


    //Do I create a constructor here for the RetrofitModule that accepts an AuthHeader object?
    
    @Provides
    @Singleton
    RequestInterceptor providesRequestInterceptor(@NonNull AuthHeader authHeader) {
        return new RequestInterceptor(authHeader);
    }

    @Provides
    @Singleton
    OkHttpClient.Builder provideOkHttp() {
        return new OkHttpClient.Builder();
    }

    @Provides
    @Singleton
    Retrofit provideRetrofit(OkHttpClient.Builder okHttpClient, RequestInterceptor requestInterceptor) {
        okHttpClient.addInterceptor(requestInterceptor);

        HttpLoggingInterceptor logging = new HttpLoggingInterceptor().setLevel(
                HttpLoggingInterceptor.Level.BASIC
        );
        okHttpClient.addInterceptor(logging);

        return new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(Constants.ENDPOINT)
                .client(okHttpClient.build())
                .build();
    }

    @Provides
    @Singleton
    LoginService provideLoginServer(Retrofit retrofit) {
        return retrofit.create(LoginService.class);
    }

}

这是AuthHeader我要传递给模块的对象,以便我可以将动态标头添加到网络调用:

public class AuthHeader {
    private String idToken;
    private String idClient;
    private String idEmail;

    public AuthHeader(String idToken, String idClient, String idEmail) {
        this.idToken = idToken;
        this.idClient = idClient;
        this.idEmail = idEmail;
    }

    public String getIdToken() {
        return idToken;
    }

    public String getIdClient() {
        return idClient;
    }

    public String getIdEmail() {
        return idEmail;
    }
}

标签: androiddagger-2

解决方案


根据您想要从 SharedPreferences 读取令牌的评论,我提供了一个完整的示例:

除了我创建AuthInfoProvider的可以读取和提供身份验证信息的代码之外。它用于代替传递 AuthHeader 对象。

class AuthInfoProvider {
    SharedPreferences preferences;

    public AuthInfoProvider(Context context) {
        preferences = context.getSharedPreferences("MyPreferences", Context.MODE_PRIVATE);
    }

    public String getToken() {
        return preferences.getString("MyToken", "");
    }
}

传递AuthInfoProvider给拦截器:

它检索每个 API 调用的令牌。

class RequestInterceptor implements Interceptor {
    private final AuthInfoProvider provider;

    public RequestInterceptor(AuthInfoProvider provider) {
        this.provider = provider;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
           Request request = chain.request().newBuilder()
                .addHeader("Authentication", provider.getToken())
                .build();
           return chain.proceed(request);
    }
}

现在我们应该将它传递给我们的模块

@Module
public class RetrofitModule {

    private static final String TAG = "RetrofitModule";

    @Provides
    @Singleton
    public static AuthInfoProvider providesAuthInfoProvider(Context context) {
        return new AuthInfoProvider(context);
    }

    @Provides
    @Singleton
    public static RequestInterceptor providesRequestInterceptor(@NonNull AuthInfoProvider authInfoProvider) {
        return new RequestInterceptor(authInfoProvider);
    }

    // other your methods
    // just make them static

}

组件将如下所示:

@Singleton
@Component(modules = RetrofitModule.class)
interface NetworkComponent {

    @Component.Builder
    interface Builder {
        Builder bindContext(@BindsInstance Context context);

        NetworkComponent build();
    }

    void inject(SampleFragment fragment);
}

并将上下文传递给组件并像这样构建它:

DaggerNetworkComponent.builder()
        .bindContext(getContext())
        .build()
        .inject(this);

推荐阅读