[英]RxJava using Kotlin - how to synchronize 2 asynchronous methods, refactor from Java
I have 2 collections, which buffer location update events: 我有2个集合,它们缓冲位置更新事件:
private List<LocationGeoEvent> mUpdateGeoEvents = new ArrayList<>();
private List<LocationRSSIEvent> mUpdateRSSIEvents = new ArrayList<>();
There is also present in my code: 我的代码中也存在:
private final ScheduledExecutorService mSaveDataExecutor = Executors.newSingleThreadScheduledExecutor();
private boolean mSaveDataScheduled;
private final Object mEventsMonitor = new Object();
private ScheduledFuture<?> mScheduledStopLocationUpdatesFuture;
private final ScheduledExecutorService mStopLocationUpdatesExecutor = Executors.newSingleThreadScheduledExecutor();
I add event to this colections like this: 我将事件添加到此集合中,如下所示:
public void appendGeoEvent(LocationGeoEvent event) {
synchronized (mEventsMonitor) {
mUpdateGeoEvents.add(event);
scheduleSaveEvents();
}
}
The same goes for the RSSI event RSSI事件也是如此
Now, the scheduleSaveEvents method looks like this: 现在,scheduleSaveEvents方法如下所示:
private void scheduleSaveEvents() {
synchronized (mSaveDataExecutor) {
if (!mSaveDataScheduled) {
mSaveDataScheduled = true;
mSaveDataExecutor.schedule(
new Runnable() {
@Override
public void run() {
synchronized (mSaveDataExecutor) {
saveEvents(false);
mSaveDataScheduled = false;
}
}
},
30,
TimeUnit.SECONDS);
}
}
}
The problem is, that i need to synchronize the other method which stops the updates. 问题是,我需要同步其他停止更新的方法。 It is triggered like this: 它是这样触发的:
private void scheduleStopLocationUpdates() {
synchronized (mStopLocationUpdatesExecutor) {
if (mScheduledStopLocationUpdatesFuture != null)
mScheduledStopLocationUpdatesFuture.cancel(true);
mScheduledStopLocationUpdatesFuture = mStopLocationUpdatesExecutor.schedule(
new Runnable() {
@Override
public void run() {
synchronized (mStopLocationUpdatesExecutor) {
stopLocationUpdates();
saveEvents(true);
cleanAllReadingsData();
}
}
},
45,
TimeUnit.SECONDS);
}
}
In the saveEvents method i do: 在saveEvents方法中,我这样做:
private void saveEvents(boolean locationUpdatesAboutToStop) {
synchronized (mEventsMonitor) {
if (mUpdateGeoEvents.size() > 0 || mUpdateRSSIEvents.size() > 0) {
//do something with the data from buffered collection arrayLists and with the boolean locationUpdatesAboutToStop
mUpdateGeoEvents.clear();
mUpdateRSSIEvents.clear();
}
}
}
Is there a way to refactor this simplier to RxJava using Kotlin? 有没有办法使用Kotlin将其简化为RxJava?
UPDATE UPDATE
Here is my appendRSSIevents method: 这是我的appendRSSIevents方法:
private fun appendRSSIEvent(event: LocationRSSIEvent) {
synchronized(mEventsMonitor) {
if (!shouldSkipRSSIData(event.nexoIdentifier)) {
mUpdateRSSIEvents.add(event)
acknowledgeDevice(event.nexoIdentifier)
scheduleSaveEvents()
startLocationUpdates()
} else
removeExpiredData()
}
}
You can buffer the two streams of data and then combine them for saving. 您可以缓冲两个数据流,然后将它们合并以保存。 Also, you can use the buffer trigger to stop the updates as well. 另外,您也可以使用缓冲区触发器来停止更新。
PublishSubject<LocationGeoEvent> mUpdateGeoEventsSubject = PublishSubject.create();
PublishSubject<LocationRSSIEvent> mUpdateRSSIEventsSubject = PublishSubject.create();
public void appendGeoEvent(LocationGeoEvent event) {
mUpdateGeoEventsSubject.onNext( event );
triggerSave.onNext( Boolean.TRUE );
}
and the same for RSS feed. 与RSS feed相同。
Now we need triggers that will be used to drive the saving step. 现在,我们需要触发器来驱动保存步骤。
PublishSubject<Boolean> triggerSave = PublishSubject.create();
PublishSubject<Boolean> triggerStopAndSave = PublishSubject.create();
Observable<Boolean> normalSaveTrigger = triggerSave.debounce( 30, TimeUnit.SECONDS );
Observable<Boolean> trigger = Observable.merge( normalSaveTrigger, triggerStopAndSave );
The trigger
observable fires when either the normal save process fires or if we are stopping the save. 当正常保存过程触发或我们停止保存时, trigger
可观察触发。
private void saveEvents(
List<LocationGeoEvent> geo,
List<LocationRSSIEvent> rss,
boolean locationUpdatesAboutToStop) {
synchronized (mEventsMonitor) {
if (geo.size() > 0 || rss.size() > 0) {
//do something with the data from buffered collection arrayLists and with the boolean locationUpdatesAboutToStop
}
}
}
private void scheduleStopLocationUpdates() {
stopLocationUpdates();
triggerStopAndSave.onNext( Boolean.FALSE );
cleanAllReadingsData();
}
Observable.zip( mUpdateGeoEventsSubject.buffer( trigger ),
mUpdateRSSIEventsSubject.buffer( trigger ),
trigger, (geo, rss, trgr) -> saveEvents(geo, rss, trgr) )
.subscribe();
You will still need to some tuning with respect to multi-threading and safety. 您仍然需要对多线程和安全性进行一些调整。 The first step would be to turn the various subjects into SerializedSubject
s so that multiple threads can emit events. 第一步是将各种主题转换为SerializedSubject
以便多个线程可以发出事件。
If you want saveEvents
to run on a particular scheduler, you will either need to add an intermediate data structure, a triple, to pass the parameters through observeOn()
operator, or apply observeOn()
operator to each of zip()
arguments. 如果要使saveEvents
在特定的调度程序上运行,则需要添加一个中间数据结构(三元组)以将参数通过observeOn()
运算符传递,或者将observeOn()
运算符应用于每个zip()
参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.