简体   繁体   English

使用Kotlin的RxJava-如何同步2种异步方法,从Java重构

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM