skip to Main Content

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;
}

2

Answers


  1. 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

    Login or Signup to reply.
  2. 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)
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search