android - 使用内部对象进行 RxJava 过滤
问题描述
首先,我必须说我是 RxJava 的初学者。
数据类:
@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()
and bookRepository.insertGoogleBook(googleBook)
Completable,并将 observable 设置为:
bookRepository.getBooksFromApi(query)
//..
.flatMap {
bookRepository.deleteGoogleBook().andThen(bookRepository.insertGoogleBook(it)).andThen(Observable.just(it))
}
//..subscribeOn
.subscribe()
- 您以这种方式混合协程和 RX 似乎很奇怪
如果您不想使用完整的 Rx,您可以考虑将 Observable 转换为 kotlin 协程流,这样会更容易处理协程取消和调用挂起函数。
我希望它有帮助
推荐阅读
- regex - 创建匹配至少一个非字母字符或字符串结尾的正则表达式
- asp.net-mvc - 在 1 个控制器中添加 2 个 ActionResult DeleteConfirmed
- android - 运动布局。OnSwipe 无法正确处理拖动事件。根本问题是什么?
- android - Android模拟新对象空指针异常
- angular - 使用路由在 Angular 6 中打开新的浏览器窗口
- javascript - 动态地将字体系列从 Assests 加载到 WebView
- powerbi - 实现相关系数时的问题
- google-apps-script - 如何从文本框中获取用户输入并导入到 google code.gs 文件中?
- powerquery - 更新现有表
- machine-learning - 咖啡的 HDF5 输入