I have 2 collections, which buffer location update events:
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
Now, the scheduleSaveEvents method looks like this:
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:
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?
UPDATE
Here is my appendRSSIevents method:
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.
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.
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.
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.