jashgopani
jashgopani

Reputation: 573

Execute function before and after variable delay in RxJava in a loop

I have an existing Java code which I want to write in RxJava. I am trying to Vibrate a device with a custom Pattern.

The custom pattern is of the format {onTime1,offTime1,onTime2,offTime2...} where, the device vibrates for onTime milliseconds and waits for offTime before next vibration.

Here is my Java code :

for (int i = 0; i < customPattern.length - 1; i++) {
            try {
                io.writeCharacteristic(Profile.UUID_SERVICE_VIBRATION, Profile.UUID_CHAR_VIBRATION, this.getProtocol());
                Thread.sleep(customPattern[i]);
                io.writeCharacteristic(Profile.UUID_SERVICE_VIBRATION, Profile.UUID_CHAR_VIBRATION, Protocol.STOP_VIBRATION);
                Thread.sleep(customPattern[i + 1]);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

EDIT I've implemented it in the following way as of now and it works just as expected. Is there a more optimised solution; I have split the array in tuples of 2 (onTime,offTime) and I am emitting those and then I am performing all on the Schedulers.computation() Thread

Observable.fromIterable(tuple).observeOn(Schedulers.io()).subscribeOn(Schedulers.computation()).subscribe(
                t->{
                    //onNext Method

                    bluetoothIo.writeCharacteristic(Profile.UUID_SERVICE_VIBRATION, Profile.UUID_CHAR_VIBRATION, Protocol.VIBRATION_WITH_LED);
                    Thread.sleep(t[0]);
                    bluetoothIo.writeCharacteristic(Profile.UUID_SERVICE_VIBRATION, Profile.UUID_CHAR_VIBRATION, Protocol.STOP_VIBRATION);
                    Thread.sleep(t[1]);
                },
                e->e.printStackTrace(),
                ()->{//onComplete}
        );

So, given this array as input {10,20,30,40,50}, I want to execute in the following manner

function1
wait(10)
function2
wait(20)
function1
wait(30)
function2
wait(40)
function1
wait(50)
function2

Upvotes: 0

Views: 554

Answers (1)

TrogDor
TrogDor

Reputation: 1029

You could do something like this.

  1. Create a Flowable representing the on-off delay pattern
  2. Create a Flowable of equal size of alternating true/false booleans indicating whether vibration should be on (or which method to call)
  3. Zip the two Flowables together and produce a Flowable of Flowables where each nested Flowable takes the on-off value and invokes the appropriate method inside doOnNext(...)
  4. Each nested Flowable subsequently delays its own value by the specified delay
  5. Finally, concatenate the nested Flowables together

You should be able to copy/paste this into your IDE:

@Test
public void testVibrate()
{
    // Delay pattern:
    Flowable<Integer> pattern = Flowable.just(
            500,    // on
            250,    // off
            500,    // on
            250,    // off
            1000,   // on
            0 );    // off
            
    // Alternating true/false booleans:
    Flowable<Boolean> onOff = pattern
            .scan(
                    true,                                   // first value
                    ( prevOnOff, delay ) -> !prevOnOff );   // subsequent values
    
    // Zip the two together
    pattern.zipWith( onOff, ( delay, on ) -> Flowable.just( on )
            .doOnNext( __ -> System.out.println( "vibrate: " + on ))    // Invoke function based on value
            .delay( delay, TimeUnit.MILLISECONDS ))                     // Delay the value downstream
    .concatMap( on -> on )                                              // Concatenate the nested flowables
    .ignoreElements()
    .blockingAwait();
}

Upvotes: 1

Related Questions