在doAsync结果中调用方法 - 主线程上的工作量太大

时间:2018-04-08 16:53:21

标签: android kotlin rx-java anko

这是我执行一些后台工作的代码

 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中存在jank,并且logcat表示在主线程上进行了太多的工作。我不明白,我在这里做错了什么?

1 个答案:

答案 0 :(得分:0)

我怀疑你创建的线程太多了。 io()无限制,computation基于处理器核心。既然你在做io,你应该使用io(),但也需要注意不要同时发出大量请求。您可以使用Flowable.flatMap来迭代列表,而不是foreach。这里的关键是将最大并发度的值指定为flatMap。下面,我已将其设置为4,但您可以使用该数字来查看在没有创建jank的情况下为最大请求空间提供良好结果的内容。另外,由于我们使用的是flatMap,因此我将subscribe移到了循环之外,以处理来自getArtistImage的结果流。目前尚不清楚您在代码段中使用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()
            })
}