Home > Software design >  I want to work with multiple base url in retrofit2
I want to work with multiple base url in retrofit2

Time:02-20

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)
}
  • Related