这是我做一些后台工作的代码
fun getAllArtists(): LiveData<List<Artist>> {
val artistListLiveData = MutableLiveData<List<Artist>>()
doAsync {
val artistList = MusicGenerator.getAllArtists()
onComplete {
getArtistInfo(artistList)
artistListLiveData.value = artistList
}
}
return artistListLiveData
}
完成后,我进行网络调用以获取艺术家信息
private fun getArtistInfo(artistList: List<Artist>) {
artistList.forEach {
val url = "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key=API_KEY&format=json"
.plus("&artist=")
.plus(it.artistName)
val artistInfoList: MutableList<ArtistInfo> = ArrayList()
apiService.getArtistImage(url)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe({ result ->
info { result.toString() }
}, { error ->
error.printStackTrace()
})
verbose { artistInfoList.size }
}
}
但是,我要确保网络调用在后台线程中进行,而结果在主线程中进行。
但是 UI 中存在卡顿,并且 logcat 显示在主线程上完成了太多工作。我不明白,我在这里做错了什么?
最佳答案
我怀疑您创建了太多线程。 io()
是无界的,计算
是基于处理器内核的。由于您正在执行 io,因此您应该使用 io()
,但还需要注意不要同时发出大量请求。您可以使用 Flowable.flatMap
代替 foreach
来遍历您的列表。这里的关键是给flatMap
指定一个最大并发值。下面,我将其设置为 4,但您可以尝试使用该数字,看看是什么在不造成卡顿的情况下为最大请求数提供了良好的结果。此外,由于我们使用的是 flatMap
,因此我将您的 subscribe
移到了循环之外,以处理来自 getArtistImage
的结果流。目前尚不清楚您在使用代码 fragment 中的 artistInfoList
做什么,因此我将其关闭,但您可以使用以下内容作为指南 -
private fun getArtistInfo(artistList: List<Artist>) {
Flowable.fromIterable(artistList).flatMap({
val url = "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key=API_KEY&format=json"
.plus("&artist=")
.plus(it.artistName)
getArtistImage(url)
.subscribeOn(Schedulers.io())
}, 4)
.subscribe({ result ->
info { result.toString() }
}, { error ->
error.printStackTrace()
})
}
关于android - 在 doAsync 结果中调用方法 - 主线程上的工作太多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49720325/