Retrofit2 deserialization / conversion on non-main

2019-07-28 04:43发布

问题:

I've referred to this answer already and it seems to be related to Retrofit v1.

Goal -> To reduce cold start time by making ObjectMapper work on non-main thread. This image shows a stack trace of it happening on the main thread.

Setup:

compile "com.squareup.retrofit2:retrofit:2.1.0"
compile "com.squareup.retrofit2:converter-jackson:2.1.0"
compile "com.squareup.retrofit2:adapter-rxjava:2.1.0"
compile 'io.reactivex:rxjava:1.1.9'

This is configuration for retrofit

.addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()))
.addConverterFactory(JacksonConverterFactory.create(ObjectMapperFactory.getObjectMapper()))

Below is a typical example of making a network call

compatibilityService().isCompatible()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(response -> { ...});

Within the JacksonConverterFactory the objectmapping seems to work on the main thread.

What is the solution without moving away from RxJava?

Possibly related posts

  • Retrofit2.0 using with rxjava will do costly reflection in mian thread even using subscribeOn()
  • https://github.com/ReactiveX/RxJava/issues/4347

回答1:

I didn't use Retrofit 1.x, but in v2 you can define return type as Response object ( i.e. Observable<Response<SomeSerializableObject>> instead of Observable<SomeSerializableObject> ) .. in this way, the deserialization shouldn't happen until user calls .body() method on it. This way, you can modify the stream through observeOn operator so that it deserializes on your specified Scheduler within map operator for example.

I can't guarantee that its possible in Retrofit 1.x as well, but you should be able to research that easily.