首先,我必须说我是RxJava中的beginer。
数据类别:
@Entity(tableName = "google_book")
data class GoogleBook (
@PrimaryKey(autoGenerate = true) val id: Int=0,
val items: ArrayList<VolumeInfo>)
data class VolumeInfo(val volumeInfo: BookInfo){
data class BookInfo(val title: String, val publisher: String, val description: String, val imageLinks: ImageLinks?)
data class ImageLinks(val smallThumbnail: String?)
}
帮助我将数据保存到数据库的功能:
fun searchBooks(query: String) {
searchJob?.cancel()
searchJob = viewModelScope.launch {
val text = query.trim()
if (text.isNotEmpty()) {
bookRepository.getBooksFromApi(query)
.map { t ->
t.items.map {
it.volumeInfo.imageLinks?.smallThumbnail?.filter { x -> x != null }
}
t
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { x ->
x?.let { googleBook ->
searchJob?.cancel()
searchJob = viewModelScope.launch {
bookRepository.deleteGoogleBook()
bookRepository.insertGoogleBook(googleBook)
}
} ?: kotlin.run {
Log.d(TAG, "observeTasks: Error")
}
}
}
}
}
如图所示,我想通过图像参数过滤GoogleBook对象中的列表,但它不起作用。我不能为数据类ImageLinks添加过滤,所以我不知道如何使其正确
我问的主要是这个部分:
.map { t ->
t.items.map {
it.volumeInfo.imageLinks?.smallThumbnail?.filter { x -> x != null }
}
t
}
感谢阅读
欢迎来到RxJava,你会喜欢它的。
据我所知,你的过滤问题只依赖于这里:
.map { t ->
t.items.map {
it.volumeInfo.imageLinks?.smallThumbnail?.filter { x -> x != null })
} // this returns you a new list filtered list here, but does not modify the original one
t // but you return the same data object here, it is not modified at all
}
// also consider naming it bookInfo if it is actually a bookInfo
你应该做的是用过滤后的元素复制你的对象,类似这样:
fun filterGoogleBookBySmallThumbNail(googleBook: GoogleBook): GoogleBook {
val filteredItems = googleBook.items.filter { it.volumeInfo.imageLinks?.smallThumbnail == null }
return googleBook.copy(items = ArrayList(filteredItems)) // now a new googleBook item is created with the filtered elements
}
// snippet to adjust then
bookRepository.getBooksFromApi(query)
.map { googleBook -> filterGoogleBookBySmallThumbNail(googleBook) }
//...
我有一些额外的注意事项/建议:
- 我看不出你真的处理了Observable的订阅
bookRepository.getBooksFromApi(query)
如果此行返回Observable,即使您取消作业,您仍将观察该Observable。如果它返回一个Single,那么你很幸运,因为在一个元素之后它就被丢弃了。为了正确处理,在取消时,你必须这样做(但我还是推荐其他两种,只是想注意不处理(:
searchJob = viewModelScope.launch {
val text = query.trim()
if (text.isNotEmpty()) {
val disposable = bookRepository.getBooksFromApi(query)
//...
.subscribe { x ->
//...
}
try {
awaitCancellation() // this actually suspends the coroutine until it is cancelled
} catch (cancellableException: CancellationException) {
disposable.dispose() // this disposes the observable subscription
// that way the coroutine stays alive as long as it's not cancelled, and at that point it actually cleans up the Rx Subscription
}
- 启动一个新的协同作业只是为了执行操作,这似乎很浪费
如果你想走Rx的路,你可以bookRepository.deleteGoogleBook()
和bookRepository.insertGoogleBook(googleBook)
可复形,并将可观测值设置为:
bookRepository.getBooksFromApi(query)
//..
.flatMap {
bookRepository.deleteGoogleBook().andThen(bookRepository.insertGoogleBook(it)).andThen(Observable.just(it))
}
//..subscribeOn
.subscribe()
如果你不想使用完整的Rx,你可以考虑将Observable转换为kotlin协程流,这将更容易处理协程取消和调用挂起函数。
我希望这对有帮助