最近,我了解到在设计应用程序后端(存储库,而不是服务器端后端)时拥有单一事实来源 (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
的建议。
另一方面,与问题本身无关,我严重怀疑 loadMore
或 moreArticles
方法的目的是什么,因为它们返回 可以完成
。在不了解上下文的情况下,您似乎可以用更好的名称重构方法名称,或者更改返回类型(如果它们按照名称执行其似乎所做的操作)。
关于Android 存储库模式和 RxJava : Use Flowable or Single?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48840087/