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

通过开发新闻源应用程序(使用很棒的https://newsapi.org/),我试图了解有关应用程序体系结构的更多信息。
但是,我不确定如何为我的应用程序设计存储库接口(interface)。
顺便说一句:我正在将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中已加载的更多数据等),则Flowable会发出数据。但是,我不确定对SearchArticleRepository#searchArticles(...)使用Flowable是否有意义。就像一些请求/响应一样,也许“单例”可能更直观。

方法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相关的问题来检查存储库更改。换句话说,对于您的用例,完全不需要IMHO背压。

检查this official guide,它为我们提供了何时通过Flowable进行Observable的建议。

另一方面,与问题本身无关,我对loadMoremoreArticles方法的用途有严重怀疑,因为它们返回Completable。在不知道上下文的情况下,似乎您可以通过更好的名称来重构方法名称,或者如果它们按照名称执行了似乎要执行的操作,则可以更改返回类型。

关于android - Android资源库模式和RxJava:使用Flowable还是Single?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48840087/

10-10 19:39