我想使用Retrofit2库进行API调用,返回泛型类型observable。
我收到错误:android.os.NetworkOnMainThreadException,同时拨打电话。
答案 0 :(得分:7)
看起来很容易解决,需要考虑两种情况。:1)如果你没有使用RXJava或2)如果你正在使用它
1)如果您不使用RXJava
拨打电话时,您应该使用enqueue方法。您得到的错误是因为您在同一个线程(MainThread)上调用响应
以下是使用Enotue with Kotlin的网站上的示例,可能您可以适应您的情况
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)如果你正在使用RXJava (通常是版本2,请注意你会在网上找到第一个版本的几个教程)
但是请考虑今天大多数开发人员使用RXJava2来解决这个异步调用,这是我在帖子开头提到的第二个案例。 需要几个小时才能理解它的基础,但是一旦你做到了,你就会有很高的技巧可以带来并管理这种电话(即使是多个电话)也很简单。事实上,RXJava允许您非常容易地在并发线程中指导操作并在主线程上观察结果。这是一个很好的教程,解释了如何do that 用简单而众所周知的模式(参见符号)
Observable<List<TrendsResponse>>
.subscribeOn(Schedulers.io())//Run the call on another Thread
.observeOn(AndroidSchedulers.mainThread())//observe on the Main Thread
.subscribe();
与RXJava的新人不同的是:
默认RXJava上的 不会调用并发线程 ,由你来完成所有&#34;脏&#34;的subcribeOn
。工作,然后用ObserveOn
在主线程上观察结果。
对于主体来说很容易理解,将它们与两种着名的AsyncTask方法进行比较:doInBackground
和onPostExecute
编辑:如果您或将来的用户遇到问题,请同时查看此post。
答案 1 :(得分:1)
使用Retrofit / RxJava,网络调用将默认在订阅从存根返回的Observable的线程上执行。在Android上,我们通常在&#34; main&#34;线程,并且不允许在此线程上访问网络,因此出错。
解决方案是告诉RxJava在不同的线程上订阅Observable:
getDataFromAPI(/*...*/)
.subscribeOn(Schedulers.io())
.observerOn(AndroidSchedulers.mainThread())
.subscribe({ /* result available in `it` */ })
Schedulers.io()
是对调度程序的引用,该调度程序使用一组专门用于IO操作的线程。
.observeOn
允许您安全地在主线程上处理结果。