You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Retrofit.Builder or retrofit.newBuilder shares same instance for converters. So you are not able to add / remove converter and don't affect original instance. There is missing some copy function in newBuilder.
For example, we need two different converters, due to external library (which need GSON converter), but for app we uses KotlinX Serialization.
In that case, we expect solution like:
But it affects the origin instance as well! Because newBuilder didn't copy instance but just reuse origin one. So converterFactories().clear() remove from origin retrofit existing converter and add new one addConverterFactory(converterFactory). So new request to external library start failing due to wrong converters.
Same solution is, if you create singleton instance without converters and try to add later:
@Provides
@Singleton
@RetrofitQualifier
internalfunprovideRetrofit(
baseUrl:HttpUrl,
okHttpClient:OkHttpClient,
pinningStrategy:PinningStrategy,
): Retrofit=Retrofit
.Builder()
.baseUrl(baseUrl)
.client(
okHttpClient
.newBuilder()
.setPinningStrategy(pinningStrategy)
.build(),
)
.build()
@Provides
@GsonRetrofitQualifier
@Singleton
funprovideGsonRetrofit(
@GsonQualifier converterFactory:Converter.Factory,
@RetrofitQualifier retrofit:Retrofit,
): Retrofit= retrofit.newBuilder()
.also { Log.d("Retro GSON", retrofitBuilder.converterFactories().count().toString()) } // Expecting all the time 0.
.addConverterFactory(converterFactory)
.also { Log.d("Retro GSON", retrofitBuilder.converterFactories().count().toString()) } // Expecting all the time 1.
.build()
@Provides
@KotlinxSerializationRetrofitQualifier
@Singleton
funprovideKotlinxSerializationRetrofit(
@KotlinxSerializationQualifier converterFactory:Converter.Factory,
@RetrofitQualifier retrofit:Retrofit,
): Retrofit= retrofit.newBuilder()
.also { Log.d("Retro KS", retrofitBuilder.converterFactories().count().toString()) } // Expecting all the time 0.
.addConverterFactory(converterFactory)
.also { Log.d("Retro KS", retrofitBuilder.converterFactories().count().toString()) } // Expecting all the time 1.
.build()
@Qualifier
annotationclassRetrofitQualifier
@Qualifier
annotationclassGsonRetrofitQualifier
@Qualifier
annotationclassKotlinxSerializationRetrofitQualifier
But if you will call second instance with different converter, it will not print to console 1 but 2 for converters. So builder again reuses same instance.
Workaround is, not to use newBuilder and not use @Singleton for @RetrofitQualifier. So we create 2 (or more) instances of base retrofit. But it's not much clear and we spend a lot of time checking what's wrong with requests.
Expected result:
newBuilder can remove converters and will not affect origin instance.
creating new instances from retrofit without factories will add only proper converter, and will not share same inner instance with different instances.
How to test it:
Create two APIs which uses different converter + serialization with name conversion:
If you will try to use converter for names data > myData it will fails when wrong convertor is used (because it will fry to parse myData entity instead of data entity).
The text was updated successfully, but these errors were encountered:
mtrakal
changed the title
Singleton Builder with addConverterFactory wrong behavior
Builder with clear/addConverterFactory wrong behavior
Oct 14, 2024
Retrofit.Builder or retrofit.newBuilder shares same instance for converters. So you are not able to add / remove converter and don't affect original instance. There is missing some copy function in newBuilder.
For example, we need two different converters, due to external library (which need GSON converter), but for app we uses KotlinX Serialization.
In that case, we expect solution like:
But it affects the origin instance as well! Because newBuilder didn't copy instance but just reuse origin one. So
converterFactories().clear()
remove from origin retrofit existing converter and add new oneaddConverterFactory(converterFactory)
. So new request to external library start failing due to wrong converters.Same solution is, if you create singleton instance without converters and try to add later:
But if you will call second instance with different converter, it will not print to console 1 but 2 for converters. So builder again reuses same instance.
Workaround is, not to use newBuilder and not use
@Singleton
for@RetrofitQualifier
. So we create 2 (or more) instances of base retrofit. But it's not much clear and we spend a lot of time checking what's wrong with requests.Expected result:
How to test it:
Create two APIs which uses different converter + serialization with name conversion:
vs
If you will try to use converter for names
data > myData
it will fails when wrong convertor is used (because it will fry to parsemyData
entity instead ofdata
entity).The text was updated successfully, but these errors were encountered: