У меня есть пример рабочего кода для аутентификации Api на основе токенов (Laravel Passport), но без Dagger 2. Я хочу переместить код из текущего RetrofitBuilder.java
в AppModule, чтобы я мог использовать силу Dagger 2 вприложение.
На данный момент, без зависимости от кинжала, у меня есть два статических метода в RetrofitBuilder.java
, которые можно использовать для вызовов с аутентифицированными маршрутами и вызовов без аутентификации:
1) createService(service)
// который выполняет вызов API без заголовков авторизации (без токена доступа)
2) createServiceWithAuth(service, tokenManager)
// который выполняет вызов API с заголовками авторизации, например с токеном доступа
Как добиться той же функциональности, используя зависимость Dagger.Как я могу обеспечить предоставление этих двух выше методов моему классу бизнес-логики, например, UserRepository.java
, чтобы я мог выполнять аутентифицированные и неаутентифицированные сервисные вызовы в любом месте, где это необходимо.
RetrofitBuilder.java
public class RetrofitBuilder {
private static final String BASE_URL = "https://api.com/";
private final static OkHttpClient client = buildClient();
private final static Retrofit retrofit = buildRetrofit(client);
private static OkHttpClient buildClient(){
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder builder = request.newBuilder()
.addHeader("Accept", "application/json")
.addHeader("Connection", "close");
request = builder.build();
return chain.proceed(request);
}
});
if(BuildConfig.DEBUG){
builder.addNetworkInterceptor(new StethoInterceptor());
}
return builder.build();
}
private static Retrofit buildRetrofit(OkHttpClient client){
return new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(MoshiConverterFactory.create())
.build();
}
public static <T> T createService(Class<T> service){
return retrofit.create(service);
}
public static <T> T createServiceWithAuth(Class<T> service, final TokenManager tokenManager){
OkHttpClient newClient = client.newBuilder().addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder builder = request.newBuilder();
if(tokenManager.getToken().getAccessToken() != null){
builder.addHeader("Authorization", "Bearer " + tokenManager.getToken().getAccessToken());
}
request = builder.build();
return chain.proceed(request);
}
}).authenticator(CustomAuthenticator.getInstance(tokenManager)).build();
Retrofit newRetrofit = retrofit.newBuilder().client(newClient).build();
return newRetrofit.create(service);
}
public static Retrofit getRetrofit() {
return retrofit;
}
}
CustomAuthenticator.java (обновляет токен, если срок действия маркера истек)
public class CustomAuthenticator implements Authenticator {
private TokenManager tokenManager;
private static CustomAuthenticator INSTANCE;
private CustomAuthenticator(TokenManager tokenManager){
this.tokenManager = tokenManager;
}
static synchronized CustomAuthenticator getInstance(TokenManager tokenManager){
if(INSTANCE == null){
INSTANCE = new CustomAuthenticator(tokenManager);
}
return INSTANCE;
}
@Nullable
@Override
public Request authenticate(Route route, Response response) throws IOException {
if(responseCount(response) >= 3){
return null;
}
AccessToken token = tokenManager.getToken();
ApiService service = RetrofitBuilder.createService(ApiService.class);
Call<AccessToken> call = service.refresh(token.getRefreshToken() + "a");
retrofit2.Response<AccessToken> res = call.execute();
if(res.isSuccessful()){
AccessToken newToken = res.body();
tokenManager.saveToken(newToken);
return response.request().newBuilder().header("Authorization", "Bearer " + res.body().getAccessToken()).build();
}else{
return null;
}
}
private int responseCount(Response response) {
int result = 1;
while ((response = response.priorResponse()) != null) {
result++;
}
return result;
}
}
AppModule.java
@Module(includes = ViewModelModule.class)
public class AppModule {
// --- DATABASE INJECTION ---
@Provides
@Singleton
MyDatabase provideDatabase(Application application) {
return Room.databaseBuilder(application,
MyDatabase.class, "MyDatabase.db")
.build();
}
@Provides
@Singleton
UserDao provideUserDao(MyDatabase database) { return database.userDao(); }
// --- REPOSITORY INJECTION ---
@Provides
Executor provideExecutor() {
return Executors.newSingleThreadExecutor();
}
@Provides
@Singleton
UserRepository provideUserRepository(UserWebservice webservice, UserDao userDao, Executor executor) {
return new UserRepository(webservice, userDao, executor);
}
// --- NETWORK INJECTION ---
private static String BASE_URL = "https://api.com/";
@Provides
Gson provideGson() { return new GsonBuilder().create(); }
@Provides
Retrofit provideRetrofit(Gson gson) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(BASE_URL)
.build();
return retrofit;
}
@Provides
@Singleton
UserWebservice provideApiWebservice(Retrofit restAdapter) {
return restAdapter.create(UserWebservice.class);
}
}