使用RxJava

时间:2017-08-30 16:40:56

标签: android caching rx-java

我有一个必须在线和离线工作的Android应用。 正在从REST端点检索数据,并在CouchDBLite实例中本地缓存数据。 记录可以在离线和在线修改,因此我在我的对象上有一些属性,用于将对象设置为脏或删除。我不会详细介绍它,因为它不相关,但这种行为是要求的一部分。

我目前正在使用Retrofit 2和RxJava 1.x,我想出了一个工作函数来检索我需要的数据。

流程应遵循以下方案:

         +------------------------------+
         |                              |
         |                              |
      +--v---+                          |
      |      |         +-----------+    |
+----->  UI  +---+----^+ DB getAll +----+
      |      |   |     +-----------+
      ++-----+   |
       ^         |
       |         ^
       |   +-----+------+
       |   | if canSync |
       |   +-----+------+
       |         | YES
       |         ^
       |  +------+--------+     +-----------+    +-----------+     +------------+    +----------+     +---------+
       |  | DB load DIRTY +----^+REST upload+---^+REST getAll+----^+set lastSync+---^+compare DB+----^+update DB|
       |  +---------------+     |DIRTY      |    +-----------+     +------------+    |lastUpdate|     +----+----+
       |                        +-----------+                                        +----------+          |
       |                                                                                                   |
       |                                                                                                   |
       |                                                                                            +------v------------+
       |                                                                                     YES    |DB getAll          |
       +--------------------------------------------------------------------------------------------+returned 0 results?|
                                                                                                    +-------------------+

以上流程基于以下规则:

  • 只有在DB中没有数据的情况下,我们才会返回从REST服务检索到的数据。那样我们就避免了 在用户更改数据时刷新UI。在从中获取数据时显示微调器也很方便 如果没有缓存数据,则为服务。

现在我正在尝试简化检索数据的函数并最终使其成为通用函数,以便我可以根据需要获取的数据类型重用它。 我很难过,一只手真有帮助。

这是功能:

public Observable<List<MyTeam>> getAllMyTeam(final String idProfile) {
    return teamLocalRepository.getAllMyTeam(idProfile)
            .flatMapIterable(new Func1<List<MyTeam>, Iterable<MyTeam>>() {
                @Override
                public Iterable<MyTeam> call(List<MyTeam> myTeams) {
                    return myTeams;
                }
            })
            .flatMap(new Func1<MyTeam, Observable<MyTeam>>() {
                @Override
                public Observable<MyTeam> call(final MyTeam team) {
                    return teamRemoteRepository.syncMyTeam(team);
                }
            })
            .toList()
            .flatMap(new Func1<List<MyTeam>, Observable<List<MyTeam>>>() {
                @Override
                public Observable<List<MyTeam>> call(List<MyTeam> myTeams) {
                    if (myTeams.size() == 0) {
                        // Return the data we fetch from the network
                        return teamRemoteRepository.getAllMyTeam(idProfile)
                                .map(new Func1<List<MyTeam>, List<MyTeam>>() {
                                    @Override
                                    public List<MyTeam> call(List<MyTeam> myTeams) {
                                        return myTeams;
                                    }
                                });
                    } else {
                        // Fire off a refresh from the network and ignore it
                        teamRemoteRepository.getAllMyTeam(idProfile)
                                .subscribeOn(Schedulers.io())
                                .subscribe();
                        // Return the cached data
                        return Observable.just(myTeams);
                    }
                }
            });
}

更新

我试着让它与泛型一起工作,因为我只想写两个方法,一个用于单个项目,一个用于项目列表。 我想出的项目列表如下,但我收到了很多unchecked警告:

public Observable<List<T>> getAll(final Class<T> clazz, final Repository localRepo, final Repository remoteRepo, final String idProfile) {
    return localRepo.getAll(idProfile)
            .flatMapIterable(new Func1<List<T>, Iterable<T>>() {
                @Override
                public Iterable<T> call(List<T> items) {
                    return Collections.checkedList(items, clazz);
                }
            })
            .flatMap(new Func1<T, Observable<T>>() {
                @Override
                public Observable<T> call(final T item) {
                    return remoteRepo.sync(item);
                }
            })
            .toList()
            .flatMap(new Func1<List<T>, Observable<List<T>>>() {
                @Override
                public Observable<List<T>> call(List<T> items) {
                    if (items.size() == 0) {
                        // Return the data we fetch from the network
                        return remoteRepo.getAll(idProfile)
                                .map(new Func1<List<T>, List<T>>() {
                                    @Override
                                    public List<T> call(List<T> items) {
                                        return Collections.checkedList(items, clazz);
                                    }
                                });
                    } else {
                        // Fire off a refresh from the network and ignore it
                        remoteRepo.getAll(idProfile)
                                .subscribeOn(Schedulers.io())
                                .subscribe();
                        // Return the cached data
                        return Observable.just(items);
                    }
                }
            });
}

我想我可以抑制该方法的未经检查的警告,但也许有更好的方法。 最重要的是,我无法生成T extends SomeBaseClass,因为模型来自swagger-codegen,看起来没有办法从自定义类继承模型,这会让事情变得更难,因为我{ {1}}方法需要检查模型的某些属性才能实际工作。

0 个答案:

没有答案