Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change retrofit okhttp client at runtime

fun getClient(token: String, userId: Long, language: String = "en", maxTry: Int = 2): Retrofit {
        val okHttpClient = OkHttpClient.Builder()
        okHttpClient.readTimeout(30, TimeUnit.SECONDS)
        okHttpClient.connectTimeout(30, TimeUnit.SECONDS)
        okHttpClient.writeTimeout(90, TimeUnit.SECONDS)
        var tryCount = 0
        okHttpClient.addInterceptor { chain ->
            val original = chain.request()
            val request = original.newBuilder()
                    .addHeader("Content-Type", "application/json")
                    .addHeader("secToken", token)
                    .addHeader("userId", userId.toString()).build()
            var response = chain.proceed(request)
            while (!response.isSuccessful && tryCount < maxTry) {
                Log.d("intercept", "Request is not successful - $tryCount")
                tryCount++
                response = chain.proceed(request)
            }
            response
        }

        val builder = GsonBuilder()
        builder.registerTypeAdapter(TransModel::class.java, NotificationTypeAdapter(language))
        val gson = builder.create()

        if (retrofit == null) {
            retrofit = Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .client(okHttpClient.build())
                    .build()
        } else {

        }

        //            .client(getHttpClientForFile())
        return retrofit!!
    }

Above code is to get singleton retrofit client for every request in App.

What I need to do is what to do in else part of retrofit == null.

Here language is initialized only once. while initializing retrofit, but for second request I don't have idea to change language and maxTry count for request.

I want to change language, and maxTry at runTime. For every request there must different maxTry count and may language also.

Edit: As per suggestion of @EarlOfEgo my else part is

 retrofit!!.newBuilder().baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .client(okHttpClient.build())
                    .build()

but It is not changing language.

Edit 2: TransModel

class TransModel {

    var en: String = ""
    var gu: String = ""
    var hi: String = ""

    constructor()

    fun get(language: String): String? {
        return when (language) {
            LanguageUtil.languageEn -> {
                en
            }

            LanguageUtil.languageGu -> {
                gu
            }

            LanguageUtil.languageHi -> {
                hi
            }

            else -> {
                null
            }
        }
    }

    constructor(language: String, value: String) {
        when (language) {
            LanguageUtil.languageEn -> {
                en = value
            }

            LanguageUtil.languageGu -> {
                gu = value
            }

            LanguageUtil.languageHi -> {
                hi = value
            }
        }
    }

    fun getValueByLanguage(language: String): String? {
        return when (language) {
            LanguageUtil.languageEn -> {
                en
            }

            LanguageUtil.languageGu -> {
                gu
            }

            LanguageUtil.languageHi -> {
                hi
            }

            else -> {
                null
            }
        }
    }

    fun updateIt(title: TransModel, currentLanguage: String) {
        when (currentLanguage) {
            LanguageUtil.languageEn -> {
                gu = title.gu
                hi = title.hi
            }

            LanguageUtil.languageGu -> {
                en = title.en
                hi = title.hi
            }

            LanguageUtil.languageHi -> {
                gu = title.gu
                en = title.en
            }

        }
    }
}

and my NotificationTypeAdapter

class NotificationTypeAdapter(val language: String) : TypeAdapter<TransModel>() {
    override fun write(out: JsonWriter?, value: TransModel?) {
        if (out == null || value == null) return
        out.beginObject()
        out.name("title")
        out.value(value.getValueByLanguage(language))
        out.endObject()
    }

    override fun read(reader: JsonReader?): TransModel? {
        if (reader == null) return null
        val jsonParser = JsonParser()
        val je = jsonParser.parse(reader)
        val trans = TransModel(language, (je.asString))
        return trans
    }
}
like image 781
Lalit Jadav Avatar asked Jun 09 '18 05:06

Lalit Jadav


People also ask

What is the difference between retrofit and OkHttp?

OkHttp is a pure HTTP/SPDY client responsible for any low-level network operations, caching, requests and responses manipulation. In contrast, Retrofit is a high-level REST abstraction build on top of OkHttp. Retrofit is strongly coupled with OkHttp and makes intensive use of it.

Should I use OkHttp or retrofit?

You should use retrofit if you are trying to map your server API inside your application (type-safing). Retrofit is just an API adapter wrapped over okHTTP. If you want to type safe and modularise the interaction code with your API, use retrofit.

How do I change my retrofit URL?

as you have mentioned already, the Retrofit instance is kind of immutable (kind of what Builders are meant for). So you'd need to create another instance for the other URL you'd like to set.

What version of OkHttp does retrofit use?

You can use 3.3. 1 version for now, just add dependency in your gradle file and set OkHttpClient to Retrofit instance.


2 Answers

You can use the Retrofit method newBuilder to get a new builder and there set a different OkHttpClient with different attributes. Put something like this into your else case:

retrofit.newBuilder()
        .client(anotherOkHttpClientWithOtherAttributes.build())
        .build()
like image 111
Stephan Avatar answered Sep 22 '22 18:09

Stephan


You can change BASE_URL at runtime by passing it as a parameter with the use of @Url annotation.

@FormUrlEncoded
@POST()
fun testService(@Url baseUrl: String,
                @Field("exampleParam") exampleParam: String): Observable<String>

Please try this and let me know for any query.

like image 32
Modi Harsh Avatar answered Sep 20 '22 18:09

Modi Harsh