RxJava - two observables - java

I've got two observables - OnPeriodChanged and OnFilterChanged, and trying to figure out how to call a function for view adapter when one of them changes. I've tried .zip, but for some reason it does not get triggered:
Observable.zip(OnPeriodChanged, OnFilterChanged, (Date, Filter) -> HistoryViewModel.getScans(Date.first, Date.second, Filter)).subscribe(scans -> histAdapter.setScans(scans));
What I can use here to invoke the getter function and pass the results from it to setter?

zip will emit the items to the downstream only after both of your observables (OnPeriodChanged, OnFilterChanged) emitted. I think you are trying to
call HistoryViewModel.getScans whenever any of the item changes, with latest values of Date and Filter. You could use combineLatest instead of zip
Try changing it to
Observable.combineLatest(OnPeriodChanged, OnFilterChanged, (Date, Filter) -> HistoryViewModel.getScans(Date.first, Date.second, Filter))
.subscribe(scans -> histAdapter.setScans(scans));

Related

Given an existing Flux (FluxMap), how can I emit message to this Flux?

Our project use a external library. It has a method return FluxMap (since FluxMap is not completely public so just call it Flux):
Flux<MappedType> aFluxMap = Library.createMappingToMappedType();
I have to emit some objects to aFluxMap to get them converted to MappedType (it has private constructor, few setter), then I can:
aFluxMap.doOnNext(converted -> doJob(converted))
I expect that there is a method on Flux/Mono like:
aFluxMap.emit(myObj);
But I could not find any method like that.
I have searched "how to emit to flux dynamically", then there is a solution:
FluxProcessor p = UnicastProcessor.create().serialize();
FluxSink sink = p.sink();
sink.next(mess);
But seem that it emit to newly created flux (p), not my aFluxMap. So I want to ask is there any way to emit message to a existed Flux (or how to connect a FluxSink to a existed Flux, so that whenever FluxSink .next(mess), then the existed Flux get the message). Thank you
Note: please don't pay much attention to the stupidity of the library. We must use it
==========================================
UPDATE:
As #lkatiforis suggestion:
FluxProcessor p = //see above
Flux<MappedType> aFluxMap = Library.createMappingToMappedType();
p.flatMap(raw -> aFluxMap).subscribe();
I got another issue. Library.createMappingToMappedType() return a subscribed Flux with its source is UnicastProcessor (also subscribed).
When I call p.flatMap(raw -> aFluxMap), then internally aFluxMap get subscribed again cause its source also get subscribed again, so that I got an exception telling that "UnicastProcessor can be subscribe once". Any suggestion?
You can create a new stream and then merge the two streams into one by using one of these methods: merge, concat, zip, and their variants.
Here is an example:
Flux<MappedType> yourFlux = //...
Flux<MappedType> aFluxMap = Library.createMappingToMappedType();
Flux.merge(aFluxMap, yourFlux);
The merge operator executes a merging of the MappedType objects from the two provided publisher sequences.

Exit Observable.zip in rxjava based on condition

In RXJava, I have a 2 observables which are responses from 2 downstream calls.One downstream call is a long poll call, other is a short one and returns right away.
I am using the Observable.zip to combine the responses of both the responses.The below code works fine.
Observable
.zip(observable1, observable2)
.flatMap(update -> foo(update));
Now what I want to implement is that if the output of the short downstream call (observable1) does not content a specific value, then skip the zip i.e dont wait for the output of the longer downstream call (observable2).
I tried to implement it in the below way, but if the condition is true it doesn't zip with the observable2, but it does not even emit observable1 response.
Observable finalresponse = observable1
.takeWhile(obsResponse1 -> checkIfValueExist(obsResponse1))
.zipWith(observable2, (observable1, observable2) -> execute(observable1, observable2))
.flatMap(update -> main.execute(update));
In zip there is a rule it will return only if both of streams will emit an item so what you need to do is to filter or return Observable.empty() in observable if your object is not what you expect or you can use filter
Observable
.zip(Observable.just(1).filter(integer -> integer==1), Observable.just(2).filter(integer -> integer==3),(integer, integer2) -> integer)
.flatMap(update -> foo(update));

Writing unit tests for Java 8 streams

I have a list and I'm streaming this list to get some filtered data as:
List<Future<Accommodation>> submittedRequestList =
list.stream().filter(Objects::nonNull)
.map(config -> taskExecutorService.submit(() -> requestHandler
.handle(jobId, config))).collect(Collectors.toList());
When I wrote tests, I tried to return some data using a when():
List<Future<Accommodation>> submittedRequestList = mock(LinkedList.class);
when(list.stream().filter(Objects::nonNull)
.map(config -> executorService.submit(() -> requestHandler
.handle(JOB_ID, config))).collect(Collectors.toList())).thenReturn(submittedRequestList);
I'm getting org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
LinkedList$$EnhancerByMockitoWithCGLIB$$716dd84d cannot be returned by submit() error. How may I resolve this error by using a correct when()?
You can only mock single method calls, not entire fluent interface cascades.
Eg, you could do
Stream<Future> fs = mock(Stream.class);
when(requestList.stream()).thenReturn(fs);
Stream<Future> filtered = mock(Stream.class);
when(fs.filter(Objects::nonNull).thenReturn(filtered);
and so on.
IMO it's really not worth mocking the whole thing, just verify that all filters were called and check the contents of the result list.

RXAndroid: get List objects from the difficult List

I have been trying for a long time to execute this code on Android, looking for answers here but not successfully. I'm a beginner developer, and please understand me.
I make multiple requests using Retrofit2 and RXJava
There is the answer, JSON (Array), it's class CurrencyData in Java
[
{
"r030":978,"txt":"euro","rate":11.11111,"cc":"EUR","exchangedate":"25.09.2018"
}
]
MyAPI interface
#GET("/BankService/v1/statdirectory/exchange")
Observable<List<CurrencyData>> getCurrencyCodeDate(#Query("valcode") String valCode, #Query("date") String date);
collect requests
List<Observable<List<CurrencyData>>> requests = new ArrayList<>();
requests.add(myApi.getCurrencyCodeDate("USD","20180928"));
requests.add(myApi.getCurrencyCodeDate("EUR","20180928"));
execute requests
Observable
.zip(requests, Arrays::asList)
.toList()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
I got
[[CurrencyData{txt='Dollar USA', rate='1.111'}], [CurrencyData{txt='EURO', rate='2.222'}]]
I'm interested in how to get a List<CurrencyData> with all the CurrencyData objects.
I tried to use map and flatMap - but it does not work.
I will be very grateful.
Thank you.
Problem:
Your getCurrencyCodeDate method returns Observable of List<CurrencyData>, And you are using it inside a Observable.zip() whith zipper func as Arrays::asList.
What is happening is, Your getCurrencyCodeDate emits a List of objects and Arrays::asList is wrapping all the emitted Lists in a List. Resulting in Observable.zip() emitting List<List<>>.
On top of that .toList() operator is applied, which will again wrap emitted List<List<>> inside another List resulting in List<List<List<>>> as return type.
What you could do is, use merge operator instead of zip and use collectInto instead of toList.
Observable
.merge(requests)
.collectInto(new ArrayList<CurrencyData>(), ArrayList::addAll)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

How to get data from more than one json api

I have more than one json api ex: api1 ,api2 and api3
Each one of them has different structure from the others,
I want to get data from these three api and combine them in one recycler view , i searched about these subject but couldn’t get any useful tutorial i am already using retrofit for fetch data from only one api , should i using rxjava withe retrofit to do what i want And how .
I'm guessing you're looking for the zip method. It basically takes many observables, waits for their items - all of them- to arrive and then merges them.
So you can basically do each API call in an observable, whatever they return you'll get it all and do whatever you want with them in order to prepare them to be included in your recyclerview, and finally when the whole operation succeeds you'll populate your recyclerview.
Observable obs1 = Observable.fromCallable(// Callable 1);
Observable obs2 = Observable.fromCallable(// Callable 2);
Observable obs3 = Observable.fromCallable(// Callable 3);
Observable.zip(obs1, obs2, obs3, (o1, o2, o3) -> // something)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(o -> {
// on success
});

Categories

Resources