【问题标题】:RxJava filtering with inside object使用内部对象进行 RxJava 过滤
【发布时间】:2021-12-19 00:14:27
【问题描述】:

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

感谢阅读

【问题讨论】:

    标签: android kotlin rx-java


    【解决方案1】:

    欢迎使用 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) Completable,并将 observable 设置为:

    bookRepository.getBooksFromApi(query)
    //..
    .flatMap {
        bookRepository.deleteGoogleBook().andThen(bookRepository.insertGoogleBook(it)).andThen(Observable.just(it))
    }
    //..subscribeOn
    .subscribe()
    
    1. 您以这种方式混合协程和 RX 似乎很奇怪

    如果您不想完全 Rx,可以考虑将 Observable 转换为 kotlin 协程流,这样会更容易处理协程取消和调用挂起函数。

    希望对你有帮助

    【讨论】:

    • 感谢您的长篇回答;D。第一份工作我有两周时间学习 RxJava,非常感谢
    • 不幸的是,您的回答无效。由于 json ,我无法更改这些变量的名称。当 imageLinks 数据类不存在或图像链接不存在时,我会尝试捕捉。当我尝试使用与数据类相关的小修复时,我得到了错误,我没有在订阅中处理 onError,这不是真的
    • 我可能错过了一些括号。或者数据类的东西,让我编辑。
    • 你自己写的过滤器对我来说真的没有意义,你似乎过滤了字符?也许我遗漏了一些东西“it.volumeInfo.imageLinks?.smallThumbnail?.filter { x -> x != null }”根据您对 imageLinks 是否存在的回答编辑了答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-27
    • 2018-08-21
    • 1970-01-01
    • 1970-01-01
    • 2014-10-05
    相关资源
    最近更新 更多