I have a structure whose base url address is constantly variable. When my user changes his location in the application, I change the base url to show the closest server to him. but the retrofit client does not regenerate even though I restart the activities and change all the static variables. The only way to do this is to close the application completely and restart it.
I don't have a fixed base url. There could be 4 different locations today, 12 different locations tomorrow. so i need to find a permanent solution.
I have examined a lot in debug mode, but; When the base url changes, it never goes inside the getClient and cannot reassign the base url.
public static Retrofit retrofit = null;
// I want this address to change.
public static String baseUrl = "";
@Provides
public static Retrofit getClient() {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
@Override
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return new Date(json.getAsJsonPrimitive().getAsLong());
}
});
Gson gson = builder.create();
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("AUTHORIZATION", "" JWT_TOKEN)
.build();
return chain.proceed(request);
}
}).build();
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
return retrofit;
}
return retrofit;
}
CodePudding user response:
You can use a dynamic URL in your application during runtime. Retrofit2 introduced the @Url
annotation that allows us to pass a complete URL for an endpoint:
@GET
public Call<ResponseBody> profilePicture(@Url String url);
EDITED
You should create a new Retrofit instance when you want to use a new base URL.
public class ServiceGenerator {
public static String apiBaseUrl = "http://futurestud.io/api";
private static Retrofit retrofit;
private static Retrofit.Builder builder =
new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(apiBaseUrl);
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder();
// No need to instantiate this class.
private ServiceGenerator() {
}
public static void changeApiBaseUrl(String newApiBaseUrl) {
apiBaseUrl = newApiBaseUrl;
builder = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(apiBaseUrl);
}
public static <S> S createService(Class<S> serviceClass, AccessToken token) {
String authToken = token.getTokenType().concat(token.getAccessToken());
return createService(serviceClass, authToken);
}
// more methods
// ...
}
https://futurestud.io/tutorials/retrofit-2-how-to-change-api-base-url-at-runtime-2
CodePudding user response:
I used SharedPreferences to handle this problem:
@Singleton
@Provides
suspend fun getBaseUrl(preferencesManager: PreferencesManager): String {
return preferencesManager.getPrefBaseUrl()
}
@Singleton
@Provides
fun provideGsonBuilder(): Gson {
return GsonBuilder()
.setLenient()
.create()
}
@Provides
@Singleton
fun provideOkHttpClient( ) =
OkHttpClient
.Builder()
.connectTimeout(3, TimeUnit.MINUTES)
.readTimeout(3, TimeUnit.MINUTES)
.writeTimeout(3, TimeUnit.MINUTES)
.build()
@Singleton
@Provides
fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient, preferencesManager: PreferencesManager): Retrofit.Builder {
return Retrofit.Builder()
.baseUrl( preferencesManager.getPrefBaseUrl())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okHttpClient)
}
@Singleton
@Provides
fun provideBlogService(retrofit: Retrofit.Builder): MyApi {
return retrofit
.build()
.create(MyApi::class.java)
}