Establecer url de base dinámica utilizando Retrofit 2.0 y Dagger 2

Estoy tratando de realizar una acción de inicio de sesión utilizando Retrofit 2.0 con Dagger 2

Así es como configuro la dependencia de Retrofit

@Provides @Singleton Retrofit provideRetrofit(Gson gson, OkHttpClient client) { Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(gson) .client(client) .baseUrl(application.getUrl()) .build(); return retrofit; } 

Aquí está la interfaz de la API.

 interface LoginAPI { @GET(relative_path) Call<Boolean> logMe(); } 

Tengo tres usuarios diferentes de las URL de la base pueden abrir una sesión. Por lo tanto, no puedo establecer un URL estático al configurar la dependencia de Retrofit. He creado un setUrl () y métodos getUrl () en la clase de aplicación. Tras el inicio de sesión del usuario, establezco la URL en la aplicación antes de invocar la llamada a la API.

Yo uso la inyección perezoso para retrofit como este

 Lazy<Retrofit> retrofit 

De esta manera, Dagger inyecta la dependencia sólo cuando puedo llamar

 retrofit.get() 

Esta parte funciona bien. Tengo la url ajustada para mejorar la dependencia. Sin embargo, el problema surge cuando el usuario escribe una URL incorrecta de base (por ejemplo, mywifi.domain.com), entiende que es incorrecta y la cambia (por ejemplo, a mydata.domain.com). Ya que Dagger ya creó la dependencia para la adaptación, no volverá a hacerlo. Así que tengo que volver a abrir la aplicación y el tipo de la url correcta.

He leído diferentes publicaciones para configurar urls dinámicas en Retrofit usando Dagger. Nada realmente funcionó bien en mi caso. ¿Extraño algo?

El soporte para este caso de uso se eliminó en Retrofit2. La recomendación es usar un interceptor OkHttp en su lugar.

HostSelectionInterceptor hecho por swankjesse

 import java.io.IOException; import okhttp3.HttpUrl; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; /** An interceptor that allows runtime changes to the URL hostname. */ public final class HostSelectionInterceptor implements Interceptor { private volatile String host; public void setHost(String host) { this.host = host; } @Override public okhttp3.Response intercept(Chain chain) throws IOException { Request request = chain.request(); String host = this.host; if (host != null) { //HttpUrl newUrl = request.url().newBuilder() // .host(host) // .build(); HttpUrl newUrl = HttpUrl.parse(host); request = request.newBuilder() .url(newUrl) .build(); } return chain.proceed(request); } public static void main(String[] args) throws Exception { HostSelectionInterceptor interceptor = new HostSelectionInterceptor(); OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(interceptor) .build(); Request request = new Request.Builder() .url("http://www.coca-cola.com/robots.txt") .build(); okhttp3.Call call1 = okHttpClient.newCall(request); okhttp3.Response response1 = call1.execute(); System.out.println("RESPONSE FROM: " + response1.request().url()); System.out.println(response1.body().string()); interceptor.setHost("www.pepsi.com"); okhttp3.Call call2 = okHttpClient.newCall(request); okhttp3.Response response2 = call2.execute(); System.out.println("RESPONSE FROM: " + response2.request().url()); System.out.println(response2.body().string()); } } 

O puede reemplazar su instancia de Retrofit (y posiblemente almacenar la instancia en un RetrofitHolder en el que puede modificar la instancia en sí, y proporcionar el titular a través de Dagger) …

 public class RetrofitHolder { Retrofit retrofit; //getter, setter } 

O vuelva a usar su instancia actual de Retrofit e invente la nueva URL con reflexión, porque atornille las reglas. Retrofit tiene un parámetro baseUrl que es private final , por lo tanto, se puede acceder sólo con la reflexión.

 Field field = Retrofit.class.getDeclaredField("baseUrl"); field.setAccessible(true); okhttp3.HttpUrl newHttpUrl = HttpUrl.parse(newUrl); field.set(retrofit, newHttpUrl); 

La biblioteca Retrofit2 viene con una anotación @Url . Puede reemplazar baseUrl esta manera:

Interfaz de la API:

 public interface UserService { @GET public Call<ResponseBody> profilePicture(@Url String url); } 

Y llame a la API de esta manera:

 Retrofit retrofit = Retrofit.Builder() .baseUrl("https://your.api.url/"); .build(); UserService service = retrofit.create(UserService.class); service.profilePicture("https://s3.amazon.com/profile-picture/path"); 

Para más detalles, consulte este enlace: https://futurestud.io/tutorials/retrofit-2-how-to-use-dynamic-urls-for-requests

  • Recepción del cuerpo de respuesta en Retrofit2 pero onResponse no se recibe
  • Retrofit 2 con sólo datos de formulario
  • ¿Es posible mostrar la barra de progreso cuando se descarga a través de Retrofit 2 Asynchronous?
  • Retrofit Tiempo de respuesta más lento en los dispositivos Android reales en comparación con el emulador y la web
  • Retrofit 2.0 lanzando "IllegalArgumentException: los parámetros @Field solo se pueden usar con la codificación de formularios". ¿Cómo hacer la consulta correcta de la API y arreglarlo?
  • RxAndroid y Retrofit: No se puede crear el adaptador de llamada para io.reactivex.Observable <retrofit2.Response <okhttp3.ResponseBody >>
  • ¿Por qué los métodos asíncronos llaman antes en Retrofit 2?
  • Obtenga el objeto JSON uno por uno desde la matriz JSON en Android utilizando Retrofit y RxJava
  • Consiguió este error con retrofit2 y OkHttp3. No se puede resolver el host "<host-name>": ninguna dirección asociada con el nombre de host
  • La llamada a la API de Retrofit recibe "HTTP FAILED: java.io.IOException: Cancelled"
  • ¿Qué está causando HTTP FALLA: java.net.SocketException: Socket cerrado?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.