1. Are you ready for the Galaxy S20? Here is everything we know so far!

Best Practice: RxJava 2, Repository-Pattern, Single-Source-Of-Truth

Discussion in 'Android Development' started by eliburgi, Feb 16, 2018.

  1. eliburgi

    eliburgi Lurker
    Thread Starter

    Hi :)
    After finishing some smaller apps, I´m currently developing a news-feed application using the awesome https://newsapi.org/. This app is special because it´s my first attempt at clean-architecture, RxJava 2 and MVVM (using android architecture components).

    Recently I read about the concept of a Single-Source-Of-Truth (SSOT). Now I can think of 2 approaches on how to design the data-layer.

    Approach 1.: Use the local database as SSOT. Every repository returns a Flowable which emits everytime the requested data in the database changed. The repository contains methods to refresh local data by making API calls and storing the results in the database, This might cause some subscribed Flowables to emit data.The ViewModel typically subscribes to the repository Flowable and refreshes it´s LiveData value. This will update the view, which is using androids DiffUtil class and RecyclerView to display the new/changed data.
    Example with NewsFeedRepository below: The ViewModel subscribes to repo.loadFeed(), which will emit a list of articles upon subscribing as well as everytime the local data changes. The ViewModel will forward the new feed data to the view which will display the changed data (DiffUtil). If the user wants to refresh the feed, the ViewModel will call repo.refreshFeed() which can either succeed or fail. This will internally make an API call and insert the response data into the local database. If that succeeds, the Flowable from repo.loadFeed() will emit the new feed data which causes the view to update. Loading more (paging) works the same.
    This would work the same for all other repositories, like SearchArticleRepository.

    The following code is in Kotlin.

    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

    Approach 2.: Again use local database as SSOT. But instead of using Flowables use Singles, e.g. the repositories won´t emit data unless explicitly requested. The repositories may look like:

    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.

    • Some Advantages/Disadvantages of Approach 1.:
    • + Changes in data (SSOT) will automatically be forwarded and displayed.
    • + ViewModel doesn´t have to keep track of current feed data
    • + Bookmarking articles is simple: Call bookmark(id) -> SSOT data changed -> emit data (Flowable)
    • - Not so intuitive?
    • Some Advantages/Disadvantages of Approach 2:
    • + Looks intuitive and simple
    • - Feed data must be stored in ViewModel (e.g loadMore() returns a list of more articles which must be added to some cached feed data in the ViewModel.)
    • - Bookmarking articles not so intuitive
    So as can be seen, I am quite unsure of what´s usually the best practice when it comes to using RxJava 2 and the repository pattern.
    Any hints or recommendations would be appreciated :)




Share This Page