问题描述
我对kotlin可观察变量有疑问,我已经通过Internet和stackoverflow搜索过,但是我认为我在概念上缺少一些东西。我有dashboardRepository,它具有名为getCallsCountForWeek的方法,这基本上返回了过去7天的可流动列表,现在我需要遍历所有可流动对象,然后使用当天的用户调用次数来更新我的图表。这是我的代码
fun getCallsCountForWeek(calendar: Calendar) : List<Flowable<Float>> {
val result = ArrayList<Flowable<Float>>()
for(index in 0..6) {
calendar.add(Calendar.DAY_OF_MONTH,-index)
result.add(dashbordDao.getCallsCountForDay(customSharedPreferences.getUser()?.id!!,CustomDateTimeUtil.getStartOfDay(calendar),CustomDateTimeUtil.getEndOfDay(calendar)).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()))
}
return result
}
Observable.fromArray(dashboardRepository
.getCallsCountForWeek(calendar). map {
items -> kotlin.run {
items.forEach {
it.subscribe({
Log.e("Result"," Count: " + it)
},{
Log.e("Error","" + it)
})
}
}
}.doOnComplete {
//We will do this when it is completed
Log.e("Result","Completed")
}.doFinally {
Log.e("Result","Finally")
}.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe()
问题在于,在map通过所有flowable完成迭代之前,将调用doFinally和doOnComplete。我尝试将.zip用于flowables,但显然也无法使其正常工作。
根据堆栈溢出的其他帖子,订阅成功时将调用doOnComplete,但我希望在.map内完成所有操作后发生这种情况。
解决方法
您应该使用flatMap
或flatMapIterable
而不是map
,并且只能进行一次subscribe
通话
Observable.fromArray(dashboardRepository
.getCallsCountForWeek(calendar)
.flatMapIterable { it } // iterate over list
.flatMap { it } // use flowables from list
.doOnNext { /* do something with every item */ }
.doOnComplete {
//We will do this when it is completed
Log.e("Result","Completed")
}
.doFinally {
Log.e("Result","Finally")
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.ignoreElements () // if you already handled everything in the doOnNext
.subscribe()
,
调查了尤金·波波维奇的回答。我被指出正确的方向,然后执行了以下操作,它就起作用了。
所以,第一件事,我修改了函数以返回Single Observable列表,而不是Flowable列表,因为任何有矿石意义的人都可以。完成后,我按照Eugene的建议进行了跟踪,但是只使用了flatMapSingle而不是flatMap。
--watch
getCallsCountForWeek中的更改如下所示,基本上只使用了Single而不是Flowable,因为这样做更有意义,并且flatMapSingle提供了开箱即用的分辨率,而无需调用甚至订阅。
Observable.fromArray(dashboardRepository.getCallsCountForWeek(calendar))
.flatMapIterable { it } // iterate over list
.flatMapSingle {
it
}
.doOnNext {
barEtries.add( BarEntry(index++,it))
}
.doOnComplete {
//We will do this when it is completed
Log.e("Result","Completed "+barEtries)
setBarChartData()
}
.doFinally {
Log.e("Result","Finally")
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.ignoreElements () // if you already handled everything in the doOnNext
.subscribe()