Home How to create Asynchronous Call using Retrofit and Observables in Kotlin?
Reply: 2

How to create Asynchronous Call using Retrofit and Observables in Kotlin?

s.thakur
1#
s.thakur Published in 2017-11-14 22:10:57Z

I want to make API calls using Retrofit2 library, returns generic type observable.

I am getting an error: android.os.NetworkOnMainThreadException, while making calls.

trocchietto
2#
trocchietto Reply to 2017-11-14 22:55:02Z

Looks really easy to solve, two cases to consider. :1)If you are not using RXJava or 2) if you are using it

1) If you are NOT using RXJava

You should use the method enqueue when you make the call. The error you get is because you are calling the response on the same Thread(the MainThread)

Here is an example took from the web that uses Enqueue with Kotlin that possibly you can adapt to your case

override fun loadPokemonList(pokemonListListener: PokemonListListener) {


    call = pokemonService.getPokedex();
    call.enqueue(object : Callback<PokeDex> {
        override fun onResponse(call: Call<PokeDex>?, response: Response<PokeDex>?) {

            if (response != null && response.isSuccessful) {
                pokemonListListener.onSuccess(response.body())
            } else {
                pokemonListListener.onFailure(appContext.getString(R.string.error_fetching_data))
            }


        }

        override fun onFailure(call: Call<PokeDex>?, t: Throwable?) {
            pokemonListListener.onFailure(appContext.getString(R.string.error_fetching_data))
        }
    })


 }

2) If you are using RXJava(usually version 2, be aware you will find several tutorials for the first version online)

But please consider that most of the developers today solve this asynchronous call using RXJava2 that is the second case I was mentioning at the beginning of he post. It will take you several hours to understand the basics of it but once you will do, you will have a great skill to bring with you and manage this kind of calls( even multiple ones) will be really simple. In fact RXJava allows you really easy to direct the operation in a concurrent Thread and observe the result on the Main Thread. Here a good tutorial that explains how to do that with the easy and well known pattern (see the notations)

Observable<List<TrendsResponse>>
    .subscribeOn(Schedulers.io())//Run the call on another Thread
    .observeOn(AndroidSchedulers.mainThread())//observe on the Main Thread
    .subscribe();

Differently by what people new to RXJava think: on default RXJava does not call a concurrent Thread, is up to you to do that with the subcribeOn that does all the "dirty" work and then to observe the result on the Main Thread with ObserveOn.

For principiants is easy to grasp that comparing both of them to the two famous methods of AsyncTask: doInBackground and onPostExecute

EDIT: Please look also this post if you or future users have problems.

Myk Willis
3#
Myk Willis Reply to 2017-11-14 22:38:16Z

With Retrofit/RxJava, the network call will be default be performed on the thread that subscribes to the Observable returned from the stub. On Android, we are normally executing on the "main" thread, and it is not permitted to access the network on this thread, hence the error.

The solution is to tell RxJava to subscribe to the Observable on a different thread:

getDataFromAPI(/*...*/)
  .subscribeOn(Schedulers.io())
  .observerOn(AndroidSchedulers.mainThread())
  .subscribe({ /* result available in `it` */ })

Schedulers.io() is a reference to a scheduler that uses a set of threads specifically intended to be used for IO operations.

The .observeOn allows you to handle the result safely back on the main thread.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.339838 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO