You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Dagger 2实现Retrofit带授权与无授权接口服务的注入?

如何用Dagger 2迁移Retrofit认证服务配置

我来帮你一步步把原来RetrofitBuilder里的逻辑迁移到Dagger 2中,完美实现无认证和带认证的API调用,同时利用依赖注入的解耦优势。

1. 确保Dagger 2依赖配置(如果还没加)

首先确认你的app/build.gradle里已经添加了Dagger 2的核心依赖:

dependencies {
    // Dagger 2核心库
    implementation 'com.google.dagger:dagger:2.x'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
    // 可选:AndroidX场景下的Dagger Android支持
    implementation 'com.google.dagger:dagger-android:2.x'
    implementation 'com.google.dagger:dagger-android-support:2.x'
    annotationProcessor 'com.google.dagger:dagger-android-processor:2.x'
}

2. 配置AppModule:提供核心依赖

在你的AppModule.java中,我们需要把所有核心依赖交给Dagger管理:

2.1 提供基础上下文与TokenManager

假设你的TokenManager负责Token的存储与读取,先把它纳入Dagger的管理范围:

@Module
public class AppModule {
    private final Context context;

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

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

    @Provides
    @Singleton
    TokenManager provideTokenManager(Context context) {
        return new TokenManager(context);
    }
}

2.2 提供CustomAuthenticator实例

注意:刷新Token必须使用无认证的API服务,避免循环依赖,所以这里要提前注入无认证的ApiService(后面会配置):

@Provides
@Singleton
CustomAuthenticator provideCustomAuthenticator(TokenManager tokenManager, @Named("noAuth") ApiService noAuthApiService) {
    return new CustomAuthenticator(tokenManager, noAuthApiService);
}

2.3 配置两种Retrofit实例(用@Named区分)

我们需要创建两个Retrofit实例:一个不带认证拦截器,一个自动携带Token并绑定刷新逻辑。用@Named注解让Dagger区分同类型的实例:

// 无认证Retrofit:用于登录、刷新Token等不需要Token的请求
@Provides
@Singleton
@Named("noAuth")
Retrofit provideNoAuthRetrofit() {
    return new Retrofit.Builder()
            .baseUrl("YOUR_API_BASE_URL")
            .addConverterFactory(GsonConverterFactory.create())
            .build();
}

// 带认证Retrofit:自动添加Authorization头,绑定Token过期刷新逻辑
@Provides
@Singleton
@Named("auth")
Retrofit provideAuthRetrofit(CustomAuthenticator authenticator, TokenManager tokenManager) {
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            // 自动添加Authorization头的拦截器
            .addInterceptor(chain -> {
                Request originalRequest = chain.request();
                Request authorizedRequest = originalRequest.newBuilder()
                        .header("Authorization", "Bearer " + tokenManager.getAccessToken())
                        .build();
                return chain.proceed(authorizedRequest);
            })
            // 设置Token过期自动刷新的Authenticator
            .authenticator(authenticator)
            .build();

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

2.4 提供两种ApiService实例

基于上面的两个Retrofit实例,创建对应的业务API服务(假设你的API接口是ApiService):

// 无认证的ApiService
@Provides
@Singleton
@Named("noAuth")
ApiService provideNoAuthApiService(@Named("noAuth") Retrofit retrofit) {
    return retrofit.create(ApiService.class);
}

// 带认证的ApiService
@Provides
@Singleton
@Named("auth")
ApiService provideAuthApiService(@Named("auth") Retrofit retrofit) {
    return retrofit.create(ApiService.class);
}

3. 在UserRepository中注入两种服务

现在你可以在业务类(比如UserRepository)中通过构造函数注入这两个服务,按需调用:

public class UserRepository {
    private final ApiService noAuthApiService;
    private final ApiService authApiService;

    // 用@Inject标记构造函数,让Dagger自动注入依赖
    @Inject
    public UserRepository(@Named("noAuth") ApiService noAuthApiService, @Named("auth") ApiService authApiService) {
        this.noAuthApiService = noAuthApiService;
        this.authApiService = authApiService;
    }

    // 示例:无认证请求(比如用户登录)
    public void performLogin(String email, String password, Callback<LoginResponse> callback) {
        noAuthApiService.login(email, password).enqueue(callback);
    }

    // 示例:带认证请求(比如获取用户个人信息)
    public void getUserProfile(Callback<UserProfile> callback) {
        authApiService.getUserProfile().enqueue(callback);
    }
}

4. 配置Dagger Component并初始化

创建AppComponent接口,定义依赖注入的范围和可对外提供的实例:

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
    // 注入Application(可选,如果你需要在Application中使用依赖)
    void inject(YourApplication application);

    // 对外提供UserRepository实例,供其他业务类获取
    UserRepository userRepository();
}

然后在你的Application类中初始化Dagger Component:

public class YourApplication extends Application {
    private AppComponent appComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        // 初始化Dagger Component
        appComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this))
                .build();
        // 注入Application本身(如果需要)
        appComponent.inject(this);
    }

    public AppComponent getAppComponent() {
        return appComponent;
    }
}

5. 在业务代码中使用UserRepository

现在你可以在Activity、ViewModel等类中轻松获取UserRepository实例,调用对应接口:

// 在Activity中获取实例
UserRepository userRepository = ((YourApplication) getApplication()).getAppComponent().userRepository();

// 调用无认证登录接口
userRepository.performLogin("user@example.com", "password", new Callback<LoginResponse>() {
    @Override
    public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
        // 处理登录成功逻辑
    }

    @Override
    public void onFailure(Call<LoginResponse> call, Throwable t) {
        // 处理登录失败逻辑
    }
});

// 调用带认证的用户信息接口
userRepository.getUserProfile(new Callback<UserProfile>() {
    @Override
    public void onResponse(Call<UserProfile> call, Response<UserProfile> response) {
        // 处理获取用户信息成功逻辑
    }

    @Override
    public void onFailure(Call<UserProfile> call, Throwable t) {
        // 处理获取用户信息失败逻辑
    }
});

关键注意点

  • @Named注解的必要性:因为两个Retrofit/ApiService类型完全相同,必须用@Named或自定义限定符区分,否则Dagger会报错无法识别依赖。
  • 避免循环依赖:CustomAuthenticator的刷新逻辑必须使用无认证的ApiService,不能依赖带认证的服务,否则会出现循环依赖问题。
  • 单例Scope的使用:Retrofit、OkHttpClient、ApiService这些实例都应该设置为@Singleton,避免重复创建对象,提升应用性能。

内容的提问来源于stack exchange,提问作者Sharoon Amjid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:48:52