带有内部对象的RxJava过滤



首先,我必须说我是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) }
//...

我有一些额外的注意事项/建议:

  1. 我看不出你真的处理了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
}
  1. 启动一个新的协同作业只是为了执行操作,这似乎很浪费

如果你想走Rx的路,你可以bookRepository.deleteGoogleBook()bookRepository.insertGoogleBook(googleBook)可复形,并将可观测值设置为:

bookRepository.getBooksFromApi(query)
//..
.flatMap {
bookRepository.deleteGoogleBook().andThen(bookRepository.insertGoogleBook(it)).andThen(Observable.just(it))
}
//..subscribeOn
.subscribe()
  • 你用这种方式混合协程和RX似乎很奇怪
  • 如果你不想使用完整的Rx,你可以考虑将Observable转换为kotlin协程流,这将更容易处理协程取消和调用挂起函数。

    我希望这对有帮助

    相关内容

    • 没有找到相关文章

    最新更新