Android 使用RxJava2重新查询和更新订户

Android 使用RxJava2重新查询和更新订户,android,retrofit,rx-java,reactive-programming,rx-java2,Android,Retrofit,Rx Java,Reactive Programming,Rx Java2,我的应用程序中有一个数据层,它由一个改进服务支持。(到目前为止,只有通过网络的持久性。当我进一步开发时,我将首先添加脱机本地存储) 当我调用服务器时,改装会向我返回一个可观察的。这很有效。在我的订阅服务器中,我在订阅时收到列表,然后可以用项填充我的UI 我面临的问题是:如果列表被修改(通过某种外部机制),我如何使可观察到的重新查询改造服务并发出新的项目列表。我知道数据过时了,但我不确定如何启动重新查询 这是我的DataManager class DataManager { // Ret

我的应用程序中有一个数据层,它由一个改进服务支持。(到目前为止,只有通过网络的持久性。当我进一步开发时,我将首先添加脱机本地存储)

当我调用服务器时,改装会向我返回一个可观察的
。这很有效。在我的订阅服务器中,我在订阅时收到列表,然后可以用
项填充我的UI

我面临的问题是:如果列表被修改(通过某种外部机制),我如何使可观察到的重新查询改造服务并发出新的项目列表。我知道数据过时了,但我不确定如何启动重新查询

这是我的
DataManager

class DataManager {

    // Retrofit
    RetrofitItemsService itemsService;

    // The observalble provided by retrofit
    Observable<List<Item>> itemsObservable;

    //ctor
    public DataManager(RetrofitItemsService itemsService) {
        this.itemsService = itemsService;
    }

    /* Creates and stores an observable if one has not been created yet.
     * Returns the observable so that it can be subscribed to by the function caller
     */
    public Observable<List<Item>> getItems(){
        if(itemsObservable == null){
            itemsObservable = itemsService.getItems();
        }

        return itemsObservable;
    }

    /* Adds a new Item to the list.
     */
    public Completable addItem(Item item){
        Completable call = itemsService.addItem(item);

        call.subscribe(()->{
            /*
             < < < Here > > >
             If someone has previously called getItems before this item was added, they now have stale data.

             How can I call something like:

             itemsObservable.refreshAllSubscribers()
            */
        });

        return call;
    }
}
类数据管理器{
//改造
改造项目服务项目服务;
//改造提供的可观测性
可观测项可观测;
//执行器
公共数据管理器(项目服务项目服务){
this.itemsService=itemsService;
}
/*创建并存储一个可观察对象(如果尚未创建)。
*返回可观察对象,以便函数调用方可以订阅它
*/
公共可观察的getItems(){
if(itemsObservable==null){
itemsObservable=itemsService.getItems();
}
返回项目可服务;
}
/*将新项目添加到列表中。
*/
公共可完成添加项(项){
Completable call=itemsService.addItem(项目);
呼叫。订阅(()->{
/*
>
如果有人在添加此项之前调用过getItems,则他们现在拥有过时的数据。
我怎样才能称之为:
itemsObservable.refreshAllSubscribers()
*/
});
回电;
}
}

您要解决的问题在于可观察到的之间的差异。有很多很棒的文章你可以用谷歌搜索出来,这些文章详细描述了它们之间的差异,所以让我来描述一下基本情况

Coldobservable为每个订户创建一个新的制作人。这意味着,当两个单独的订户订阅相同的冷观测时,他们每个人都会收到这些发射的不同实例。他们可能是平等的,但他们从来都是不同的对象。应用到您的案例中,每个订阅者都有自己的生产者,生产者向服务器请求数据并将其传递到流中。每个订阅者都从其自己的生产者那里获得数据

Hotobservable与其所有观察者共享一个生产商。如果制作者例如通过对象集合迭代,在第二个订阅服务器中间跳入发射意味着它将只获得随后发射的项目(如果它没有通过像<代码>重放< /代码>之类的操作符修改)。任何订阅者接收到的每个对象在所有观察者中都是相同的实例,因为它来自一个生产者

因此,从外观上看,你需要有一个热的可观察对象来分发你的数据,这样当你知道它不再有效时,你只需通过这个热的可观察对象发出一次,每个观察者都会对更新感到满意

幸运的是,将寒冷的天气转变为炎热的天气通常不是什么大问题。您可以创建自己的制作者来模仿这种行为,使用一种流行的操作符,如
share
,或者只需变换流,使其行为类似于一个

我建议使用PublishSubject刷新数据,并将其与原始cold observable合并,如下所示:

class DataManager {

    .....

    PublishSubject<Boolean> refreshSubject = PublishSubject.create();

    // The observable for retrieving always fresh data
    Observable<List<Item>> itemsObservable;

    //ctor
    public DataManager(RetrofitItemsService itemsService) {
        this.itemsService = itemsService;
        itemsObservable = itemsService.getItems()
                              .mergeWith(refreshSubject.flatMap(refresh -> itemsService.getItems()))
    }


    public Observable<List<Item>> getItems(){
        return itemsObservable;
    }

    /* Adds a new Item to the list.
     */
    public Completable addItem(Item item){
        Completable call = itemsService.addItem(item);

        call.subscribe(()->{
            refreshSubject.onNext(true);
        });

        return call;
    }
}
类数据管理器{
.....
PublishSubject refreshSubject=PublishSubject.create();
//用于检索总是最新数据的可观察对象
可观测项可观测;
//执行器
公共数据管理器(项目服务项目服务){
this.itemsService=itemsService;
itemsObservable=itemsService.getItems()
.mergeWith(refreshSubject.flatMap(refresh->itemsService.getItems())
}
公共可观察的getItems(){
返回项目可服务;
}
/*将新项目添加到列表中。
*/
公共可完成添加项(项){
Completable call=itemsService.addItem(项目);
呼叫。订阅(()->{
refreshSubject.onNext(true);
});
回电;
}
}

您要解决的问题在于可观察到的之间的差异。有很多很棒的文章你可以用谷歌搜索出来,这些文章详细描述了它们之间的差异,所以让我来描述一下基本情况

Coldobservable为每个订户创建一个新的制作人。这意味着,当两个单独的订户订阅相同的冷观测时,他们每个人都会收到这些发射的不同实例。他们可能是平等的,但他们从来都是不同的对象。应用到您的案例中,每个订阅者都有自己的生产者,生产者向服务器请求数据并将其传递到流中。每个订阅者都从其自己的生产者那里获得数据

Hotobservable与其所有观察者共享一个生产商。如果制作者例如通过对象集合迭代,在第二个订阅服务器中间跳入发射意味着它将只获得随后发射的项目(如果它没有通过像<代码>重放< /代码>之类的操作符修改)。任何订阅者接收到的每个对象在所有观察者中都是相同的实例,因为它来自一个生产者

因此,从外观上看,你需要有一个热的可观察对象来分发你的数据,这样当你知道它不再有效时,你只需通过这个热的可观察对象发出一次,每个观察者都会对更新感到满意
final Subject<Object> onItemsChanged = PublishSubject.create().toSerialized();

public Observable<Object> itemsChanged() {
    return onItemsChanged;
}

public Completable addItem(Item item){
    Completable call = itemsService.addItem(item);

    // prevent triggering the addItem multiple times
    // Needs RxJava 2 Extensions library for now
    // as there is no Completable.cache() or equivalent in 2.0.3
    CompletableSubject cs = CompletableSubject.create();

    call.doOnComplete(() -> onItemsChanged.onNext("changed"))
    .subscribe(cs);

    return cs;
}