I made an adapter for communication class with Retrofit2 + Rx2

Introduction

It's still just a memo, so I think there are many things that are difficult to understand. I would appreciate it if you could make an edit request as appropriate.

Common writing style

It is a premise that you have a general knowledge of Retrofit and Rx. If you want to know about that, this article will be very helpful. Implement API client quickly with Retrofit and Rx in Kotlin


class MyApiDatasore {
   fun <T> createService(service: Class<T>) =
                Retrofit.Builder()
                        .baseUrl("url")
                        .addConverterFactory(JacksonConverterFactory.create(ObjectMapper()))
                        .addCallAdapterFactory(RxCallAdapterFactory.create())
                        .build()
                        .create(service)!!
}
interface MyApiService {
    @Get("hogehoge")
    fun fetchHogeHoge()

}

Caller


MyApiDatastore().createService(MyApiService::class.java)
                    .fetchHogeHoge()
                    .subscribeOn(Schedulers.newThread())       //Run in a background thread
                    .observeOn(AndroidSchedulers.mainThread()) //Notify the main thread
                    .subscribe({
                        // onSuccess
                    }) { e ->
                        // onError

                    }

problem

It's annoying to write this every time.

  ...
  .subscribeOn(Schedulers.newThread())
  .observeOn(AndroidSchedulers.mainThread())

Let's put it together

Refer to Articles around here, or refer to the documentation and make your own custom adapter that does the above every time. created.

**
 * RxJava adapter for Retrofit.
 * Always `subscribeOn(Schedulers.newThread())`
 *        `observeOn(AndroidSchedulers.mainThread())`
 */
private class RxThreadingCallAdapterFactory : CallAdapter.Factory() {

    companion object {
        fun create(): CallAdapter.Factory = RxThreadingCallAdapterFactory()
    }

    //Always run in a new thread
    private val original: RxJava2CallAdapterFactory = RxJava2CallAdapterFactory.createWithScheduler(Schedulers.newThread())

    override fun get(returnType: Type, annotations: Array<Annotation>, retrofit: Retrofit): CallAdapter<*, *> {
        // `original.get() == null` -> Retrofit throws IllegalArgumentException.
        return RxCallAdapterWrapper(original.get(returnType, annotations, retrofit)!!)
    }

    private class RxCallAdapterWrapper<R>(private val wrapped: CallAdapter<R, *>) : CallAdapter<R, Any> {
        override fun responseType(): Type = wrapped.responseType()

        //Always notify the main thread
        override fun adapt(call: Call<R>) = wrapped.adapt(call)
                .let {
                    when (it) {
                        is Completable -> {
                            it.observeOn(AndroidSchedulers.mainThread())
                        }
                        is Observable<*> -> {
                            it.observeOn(AndroidSchedulers.mainThread())
                        }
                        is Single<*> -> {
                            it.observeOn(AndroidSchedulers.mainThread())
                        }
                        is Flowable<*> -> {
                            it.observeOn(AndroidSchedulers.mainThread())
                        }
                        is Maybe<*> -> {
                            it.observeOn(AndroidSchedulers.mainThread())
                        }
                        else -> errorIfDebug()
                    }
                }!!
    }
}

How to use

By using the retrofit service as shown below, you can implement the process to run in the background and notify the main thread just by writing .subscribe every time.

      Retrofit.Builder()
              .baseUrl("url")
              .addConverterFactory(JacksonConverterFactory.create(ObjectMapper()))
              .addCallAdapterFactory(RxThreadingCallAdapterFactory.create()) //Use a custom adapter here
              .build()
              .create(service)!!

Recommended Posts

I made an adapter for communication class with Retrofit2 + Rx2
I made an eco server with scala
I made an app for myself! (Reading management app)
I made an Android app for MiRm service
I made an API client for Nature Remo
I made an iPhone Theremin with Vision framework + AudioKit
I made an Android application that GETs with HTTP
I made an interpreter (compiler?) With about 80 lines in Ruby.
I want to push an app made with Rails 6 to GitHub
I updated my own blackjack made with Ruby for my portfolio
I made a GUI with Swing
I tried UDP communication with Java
I made an annotation in Java.
Run an application made with Java8 with Java6
CentOS8 doesn't have unar binaries so I made an alternative with bash
I made an app to scribble with PencilKit on a PDF file
I made a risky die with Ruby
I made a plugin for IntelliJ IDEA
I made a rock-paper-scissors app with kotlin
I made a rock-paper-scissors app with android
The training for newcomers was "Make an app!", So I made an app for the time being.