在我的应用中,我有一项跟踪用户位置的服务,然后使用RxJava
将其发送到服务器。如果请求成功,我将收回插入的ID,然后我可以从本地数据库中删除它们。
我的问题是,我在上一个任务结束之前快速调用了observable,因此服务器会收到重复点(两个请求的点相同)。我需要在单个线程上执行Observable
以避免在上一个数据库结束之前有另一个任务查询数据库。我创建了一个Looper
主题,但我仍然发送重复项,我不知道为什么。现在服务器请求似乎要等到它在执行下一个请求之前结束,但是在下一个请求时,它仍然发送相同的点! Gahh
final StoreChangeEvent finalEvent = event;
Observable
.defer(() -> Observable.just(database.getAllPoints()))
.flatMap(pointsList -> (pointsList.isEmpty()) ? Observable.empty() : amazonRetrofit.postAmazonPoints(pointsList)
.map(result -> deletePoint(result))
.doOnError(error -> emitStoreChange(new ErrorMessageEvent(error.getMessage())))
.doOnCompleted(() -> emitStoreChange(finalEvent))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(AndroidSchedulers.from(backgroundLooper)))
.subscribe();
似乎database.getAllPoints()
太快被调用了...我应该添加.blocking()吗?
我们说我有5点要发布到服务器( A,B,C,D )
结果:A-B-C-D在服务器数据库上有两次,因为两个请求是以相同的点发送的
答案 0 :(得分:2)
您可以尝试使用Subject
- 既可作为观察者又可作为观察者的事物。
订阅一次,并在其他地方通知新事件(onNext()
)。订户将随后处理事件。
我使用了SerializedSubject
,以防您从不同的主题中调用notifyNewEvent()
,否则您可以使用BehaviourSubject
。
SerializedSubject<StoreChangeEvent, StoreChangeEvent> subject = new SerializedSubject(BehaviorSubject.create())
public void initialize() {
// Since you access your incoming event from doOnCompleted,
// need this extra flatMap function so that you can access your event
// outside rx java chain.
subject.flatMap(new Func1() {
@Override
public Observable call(StoreChangeEvent event) {
return Observable
.just(database.getAllPoints())
.flatMap(pointsList -> (pointsList.isEmpty()) ? Observable.empty() : amazonRetrofit.postAmazonPoints(pointsList)
.map(result -> deletePoint(result))
.doOnError(error -> emitStoreChange(new ErrorMessageEvent(error.getMessage())))
.doOnCompleted(() -> emitStoreChange(finalEvent)));
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(AndroidSchedulers.from(backgroundLooper))
.subscribe();
}
public void notifyNewEvent(StoreChangeEvent event) {
subject.onNext(event);
}
如果您不访问用户界面,为什么还要打扰主题并观察,请订阅。使用一个线程创建一个执行程序(随后执行所有任务),并将任务提交给它,并在那里利用RxJava有用的功能。
ExecutorService executorService = Executors.newSingleThreadExecutor();
public void notifyNewEvent(final StoreChangeEvent event) {
executorService.execute(new Runnable() {
public void run() {
Observable.just(database.getAllPoints())
// Blocking, so that the thread doesn't exit
// and blocks on subscribe() till completion.
.toBlocking()
.flatMap(pointsList -> (pointsList.isEmpty()) ? Observable.empty() : amazonRetrofit.postAmazonPoints(pointsList)
.map(result -> deletePoint(result))
.doOnError(error -> emitStoreChange(new ErrorMessageEvent(error.getMessage())))
.doOnCompleted(() -> emitStoreChange(finalEvent)))
.subscribe();
}
});
}