使用SQLBrite + Retrofit刷新数据

时间:2017-01-10 15:13:34

标签: android rx-java retrofit2 sqlbrite

这是我的用例:

我正在开发一个通过REST API与服务器通信的应用程序,并将收到的数据存储在SQLite数据库中(它将其用作某些类型的缓存)。

当用户打开屏幕时,必须进行以下操作:

  1. 如果可以,则从数据库加载数据。
  2. 该应用调用API来刷新数据。
  3. API调用的结果将保留在DB中。
  4. 截获数据更改通知时,将从数据库重新加载数据。
  5. 这与呈现here的情况非常相似,但存在细微差别。

    由于我使用的是SQLBrite,因此DB observable不会终止(因为在那里注册了ContentObserver,这会在流中推送新数据),所以像concat,{{1这样的方法等等不会起作用。

    目前,我已使用以下方法解决了这个问题:

    merge

    好像它工作正常,但它看起来并不优雅和“正确”。

    您能否建议或指出一个资源,解释处理这种情况的最佳方法是什么?

1 个答案:

答案 0 :(得分:6)

如果你改变思维方式,问题的解决方案实际上非常简单和干净。我正在使用完全相同的数据交互(Retrofit + Sqlbrite),这个解决方案非常有效。

您需要做的是使用两个单独的可观察订阅,这些订阅会处理完全不同的过程。

  1. Database -> View:此一个用于附加您的ViewActivityFragment或任何显示您的数据的内容) db中的持久数据。您为创建的View订阅了ONCE。
  2. dbObservable
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(data -> {
                displayData(data);
            }, throwable -> {
                handleError(throwable);
            });
    
    1. API -> Database:另一个从api获取数据并将其保留在数据库中。每次要刷新数据库中的数据时,都会订阅它。
    2. apiObservable
              .subscribeOn(Schedulers.io())
              .observeOn(Schedulers.io())
              .subscribe(data -> {
                 storeDataInDatabase(data);
              }, throwable -> {
                  handleError(throwable);
              });
      

      编辑:

      你不想改变"这两种观察结果都是一体的,纯粹是出于你的问题所包含的原因。两个可观察者的行为完全不同。

      来自Retrofit的observable就像一个Single。它完成它需要做的事情,并完成(使用onCompleted)。

      来自Sqlbrite的observable是一个典型的Observable,它会在每次特定表更改时发出一些内容。从理论上讲,它应该在未来完成。

      Ofc你可以解决这个问题,但它会带你走远,远离那些干净易读的代码。

      如果您确实需要公开单个observable,那么在订阅您的数据库时,您可以隐藏您实际订阅可观察对象的事实

      1. 用方法包装Api订阅:
      2. public void fetchRemoteData() {
            apiObservable
                    .subscribeOn(Schedulers.io())
                    .observeOn(Schedulers.io())
                    .subscribe(data -> {
                        persistData(data);
                    }, throwable -> {
                        handleError(throwable);
                    });
        }
        
          订阅
        1. fetchRemoteData
        2. dbObservable
                  .subscribeOn(Schedulers.io())
                  .observeOn(AndroidSchedulers.mainThread())
                  .doOnSubscribe(() -> fetchRemoteData())
                  .subscribe(data -> {
                      displayData(data);
                  }, throwable -> {
                      handleError(throwable);
                  });
          

          我建议你真的考虑这一切。因为你强迫自己进入你需要一个可观察的位置的事实,可能会严重限制你。我相信这将会迫使你在将来改变你的概念,而不是保护你免受改变本身的影响。