Android 存储库模式和 RxJava : Use Flowable or Single?

标签 android kotlin rx-java2

最近,我了解到在设计应用程序后端(存储库,而不是服务器端后端)时拥有单一事实来源 (SSOT) 的重要性。 https://developer.android.com/topic/libraries/architecture/guide.html

通过开发一个新闻源应用程序(使用很棒的 https://newsapi.org/ ),我试图了解有关应用程序架构的更多信息。 但是,我不确定如何为我的应用程序设计存储库界面。 顺便说一句:我正在使用 MVVM 作为我的表示层。 View 订阅 ViewModel 的 LiveData。 ViewModel 订阅 RxJava 流。

所以我想出了两种方法:

方法 1:

interface NewsFeedRepository {
        fun loadFeed(): Flowable<List<Article>>
        fun refreshFeed(): Completable
        fun loadMore(): Completable
    }

interface SearchArticleRepository {
    fun searchArticles(sources: List<NewsSource>? = null, query: String? = null): Flowable<List<Article>>
    fun moreArticles(): Completable
}

interface BookmarkRepository {
    fun getBookmarkedArticles(): Flowable<List<Article>>
    fun bookmarkArticle(id: String): Completable
}

此方法主要使用 Flowables,如果底层 SSOT(数据库)中的相应数据发生变化(例如旧数据被来自 API 的新数据替换,更多数据从 API 加载,...),则 Flowables 会发出数据。但是,我不确定将 Flowable 用于 SearchArticleRepository#searchArticles(...) 是否有意义。因为它就像一些请求/响应的事情,也许单例可能会更直观。

方法 2:

interface NewsFeedRepository {
    fun loadFeed(): Single<List<Article>>
    fun refreshFeed(): Single<List<Article>>
    fun loadMore(): Single<List<Article>>
}

interface SearchArticleRepository {
    fun searchArticles(sources: List<NewsSource>? = null, query: String? = null): Single<List<Article>>
    fun moreArticles(): Single<List<Article>>​
}

interface BookmarkRepository {
    fun getBookmarkedArticles(): Single<List<Article>>
    fun bookmarkArticle(id: String): Single<Article> // Returns the article that was modified. Articles are immutable. ​
}

这种方法使用 Singles 而不是 Flowables。这看起来非常直观,但如果 SSOT 中的数据发生变化,则不会发出任何变化。相反,必须再次调用存储库。另一个需要考虑的方面是 ViewModel 可能必须管理自己的状态。 让我们以 FeedViewModel 为例(伪代码)。

class FeedViewModel : ViewModel() {
    // Variables, Boilerplate, ...
    val newsFeed: LiveData<List<Article>>
    private val articles = mutableListOf<Article>()

    fun loadNewsFeed() {
        // ...
        repository.loadFeed()
                   //...
                   // On success, clear the feed and append the loaded articles.
                  .subscribe({articles.clear(); articles.addAll(it)})
        // ...
    } 

    fun loadMore() {
        // ...
        repository.loadMore()
                   //...
                   // On success, append the newly loaded articles to the feed.
                  .subscribe({articles.addAll(it)}) 
        // ...
    }
}

因此,这对于像我这样的较小应用程序来说可能并不重要,但对于较大的应用程序来说肯定会出现问题(请参阅状态管理: http://hannesdorfmann.com/android/arch-components-purist )。

最后,我想知道采用哪种方法以及原因。 有任何最佳实践吗?我知道你们中的许多人已经完成了一些较大的软件项目/应用程序,如果你们中的一些人可以与我和其他人分享一些知识,那就太棒了。

非常感谢!

最佳答案

在您的情况下,我宁愿选择使用 Observable 而不是 Flowable 的第一种方法:

interface NewsFeedRepository {
    fun loadFeed(): Observable<List<Article>>
    fun refreshFeed(): Completable
    fun loadMore(): Completable
}

interface SearchArticleRepository {
    fun searchArticles(sources: List<NewsSource>? = null, query: String? = null): Observable<List<Article>>
    fun moreArticles(): Completable
}

interface BookmarkRepository {
    fun getBookmarkedArticles(): Observable<List<Article>>
    fun bookmarkArticle(id: String): Completable
}

我认为您没有任何理由必须使用 Flowable 来实现此目的,因为在检查存储库更改时您永远不会遇到任何 OOME 相关问题。换句话说,对于您的用例,恕我直言,背压根本没有必要。

检查this official guide这为我们提供了何时使用 Flowable 而不是 Observable 的建议。

另一方面,与问题本身无关,我严重怀疑 loadMoremoreArticles 方法的目的是什么,因为它们返回 可以完成。在不了解上下文的情况下,您似乎可以用更好的名称重构方法名称,或者更改返回类型(如果它们按照名称执行其似乎所做的操作)。

关于Android 存储库模式和 RxJava : Use Flowable or Single?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48840087/

相关文章:

java - Android Studio中添加JsonPath导致非零退出值2错误

android - 在 android 项目中重新生成 R 类 (eclipse)

java - 如何使用 RxJava2 从无限 Stream<Integer> 创建 Observable<Integer>?

android - Worker 内部的 Synchronous 或 Asynchronous Rxjava(来自 WorkManager 组件)什么是正确的选择?

android - RxJava/Kotlin Observable 方法调用链 - 如何终止?

android - file.createFile不起作用。 Android 10

android - 使用 Android 应用程序远程监控 SCADA

documentation - 如何在 kotlin kDoc 中使用 @link 和 @code

kotlin - 从标签 Kotlin 的内部嵌套协程返回

android - 在 ViewPager2 中是否有特殊的解决方案?