Dagger + Retrofit URL dinámica

PROBLEMA

Necesito llamar a la API de los dominios ingresados ​​por el USUARIO y necesito editar mi singleton Retrofit antes de la llamada en consecuencia a los datos insertados.

¿Hay una manera de "restablecer" mi singleton, obligándolo a recrear?

o

¿Hay alguna manera de actualizar mi baseUrl con mis datos (tal vez en Interceptor?) Justo antes de llamar?

CÓDIGO

Singletons

 @Provides @Singleton Retrofit provideRetrofit(SharedPreferences prefs) { String apiUrl = "https://%1s%2s"; apiUrl = String.format(apiUrl, prefs.getString(ACCOUNT_SUBDOMAIN, null), prefs.getString(ACCOUNT_DOMAIN, null)); OkHttpClient httpClient = new OkHttpClient.Builder() .addInterceptor(new HeaderInterceptor()) .build(); return new Retrofit.Builder() .baseUrl(apiUrl) .addConverterFactory(GsonConverterFactory.create()) .client(httpClient) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); } @Provides @Singleton API provideAPI(Retrofit retrofit) { return retrofit.create(API.class); } 

API

 @FormUrlEncoded @POST("endpoint") Observable<Response> logIn(@Field("login") String login, @Field("password") String password); 

Cómo funciona ahora

Bueno, la idea era guardar datos de dominio de usuario a través de SharedPrefs antes de la llamada API y modificar baseUrl con String con formato.

Veo 2 opciones aquí:

  • Utilice la daga como se pretende. Crear para cada baseUrl su propio cliente de Retrofit , o
  • Utilice un interceptor para modificar la solicitud antes de enviarla

Acercamiento de la daga

Si fueras a urls de fuerza bruta, esto probablemente no sería la elección correcta, ya que se basa en la creación de una nueva instancia de Retrofit para cada uno.

Ahora cada vez que la url cambia, usted acaba de recrear el siguiente UrlComponent demostrado al suministrarlo con un nuevo UrlModule .

Limpiar

Limpie su módulo @Singleton , para que proporcione GsonConverterFactory , y RxJavaCallAdapterFactory para hacer un uso adecuado de la daga y no recrear objetos compartidos.

 @Module public class SingletonModule { @Provides @Singleton GsonConverterFactory provideOkHttpClient() {/**/} @Provides @Singleton RxJavaCallAdapterFactory provideOkHttpClient() {/**/} } @Singleton @Component(modules = SingletonModule.class) interface SingletonComponent { // sub component UrlComponent plus(UrlModule component); } 

Url Scoped

Introduzca un @UrlScope para el alcance de las instancias de Retrofit .

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

A continuación, cree un subcomponente

 @SubComponent(modules=UrlModule.class) public interface UrlComponent {} 

Y un módulo para ello

 @Module class UrlModule { private final String mUrl; UrlModule(String url) { mUrl = url; } @Provides String provideUrl() { return mUrl; } @Provides @UrlScope OkHttpClient provideOkHttpClient(String url) { return new OkHttpClient.Builder().build(); } @Provides @UrlScope Retrofit provideRetrofit(OkHttpClient client) { return new Retrofit.Builder().build(); } } 

Utilizar retroalimentación con alcance

Instanciar el componente y utilizarlo.

 class Dagger { public void demo() { UrlModule module = new UrlModule(/*some url*/); SingletonComponent singletonComponent = DaggerSingletonComponent.create(); UrlComponent urlComponent = singletonComponent.plus(module); urlComponent.getRetrofit(); // done. } } 

Enfoque OkHttp

Proporcione un interceptor con un alcance adecuado ( @Singleton en este caso) e implemente la lógica correspondiente.

 @Module class SingletonModule { @Provides @Singleton GsonConverterFactory provideGsonConverter() { /**/ } @Provides @Singleton RxJavaCallAdapterFactory provideRxJavaCallAdapter() { /**/ } @Provides @Singleton MyApiInterceptor provideMyApiInterceptor() { /**/ } @Provides @Singleton OkHttpClient provideOkHttpClient(MyApiInterceptor interceptor) { return new OkHttpClient.Builder().build(); } @Provides @Singleton Retrofit provideRetrofit(OkHttpClient client) { return new Retrofit.Builder().build(); } } @Singleton @Component(modules = SingletonModule.class) interface SingletonComponent { Retrofit getRetrofit(); MyApiInterceptor getInterceptor(); } 

Todo Implementar MyApiInterceptor . Necesitará tener un setter para la url de base, y luego simplemente reescribir / modificar las peticiones que vienen a través.

Entonces, otra vez, apenas vaya a continuación y utilícelo.

 class Dagger { public void demo() { SingletonComponent singletonComponent = DaggerSingletonComponent.create(); MyService service = singletonComponent.getRetrofit().create(MyService.class); MyApiInterceptor interceptor = singletonComponent.getInterceptor(); interceptor.setBaseUrl(myUrlA); service.doA(); interceptor.setBaseUrl(someOtherUrl); service.doB(); } } 

Como un tercer enfoque, también podría utilizar la reflexión para cambiar directamente la base de base de la URL-He añadido este último sólo para la integridad.

Puede implementar BaseUrl y pasarlo en lugar de una URL fija. Echa un vistazo a este enlace Otro enfoque es la implementación de Endpoint y hacer uso de setUrl() . Así que para cambiar algún valor de encabezado en tiempo de ejecución, a continuación, puede utilizar interceptor y agregarlo a OkHttp.

  • Cómo migrar la inyección que falta del módulo con complete = false de Dagger 1 a Dagger 2
  • Dagger no puede crear el gráfico del objeto aunque puede producir el archivo del punto
  • @Named proveedores con los mismos tipos de retorno terminan dando java.lang.IllegalArgumentException: Duplicar
  • NPE al obtener Robolectric ShadowApplication con Volley y Dagger
  • VerifyError en la aplicación multidex al inyectar dependencia con Dagger
  • Sustitución de las inyecciones de Proveedor por Mockito durante la prueba con Dagger
  • Cómo reemplazar dependencias dentro de Scopes en Dagger 2
  • Código de la daga que da NoClassDefFoundError cuando las pruebas de Espresso se ejecutan, funcionamiento normal trabaja muy bien
  • Dagger 2 problema sobreponiendo único proporciona el método anotado de un módulo en una biblioteca que la aplicación utiliza
  • Bus de eventos Otto que recibe múltiples eventos en una sola entrada
  • Daga con Android: ¿Cómo inyectar el contexto cuando se utiliza MVP?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.