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.
- Dagger 2 en Android: inyectar la misma dependencia en Activity y retener Fragment
- ¿Cuál es el razonamiento para separar los métodos RestAdapter.build () y .create () al usar Dagger?
- Inyección de dependencia de Java: Dagger 1 vs Dagger 2, que es mejor?
- Dagger gráfico de actividad y módulos separados
- Dagger- ¿Debemos crear cada componente y módulo para cada Actividad / Fragmento
¿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.
- Prueba funcional de Android con Dagger
- La daga no puede inyectar el campo del parámetro del tipo
- Dagger2 androidTest error entrada duplicada: javax / annotation / Generated.class
- La clase Dagger no podía estar atada con la clave
- ¿Cómo configurar la inyección de dependencia con Dagger para otras cosas que no sean Actividades y Fragmentos?
- Gradle Build Error - NullPointerException lanzado durante la aplicación: compileDebugJava gradle task
- Añadir Retrofit Requestinterceptor con Dagger en tiempo de ejecución
- Daga 2: java.lang.NoSuchMethodError
Veo 2 opciones aquí:
- Utilice la daga como se pretende. Crear para cada
baseUrl
su propio cliente deRetrofit
, 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.
- Android ActionBar setActionView problema de diseño
- No se encontró ningún identificador de recurso para el atributo 'roundIcon' en el paquete 'android'