Dagger2 - 将 Object 传递给模块的最佳实践?

Dagger2 - Best practice for passing an Object to a Module?

我正在尝试创建 RetrofitModule。我有一个 interceptor,它使用 AuthHeader object 添加动态 headers。我不确定如何将此 object 传递给模块 class.

@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 object 以便我可以将动态 headers 添加到网络调用中:

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

根据您的意见,您想从 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);