I want to make API calls using Retrofit2 library, returns generic type observable.
I am getting an error: android.os.NetworkOnMainThreadException, while making calls.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With