how to convert Observable<List<A>>to Flowable<A>. Rx Java - rx-java2

I tried to convert Observable<List> to Flowable
RxJava, however it doesn't work. Would you give an advice or a solution?, thanks in advaced.
return resource.flatMap(
new Function<Observable<List<Product>>, List<Product>>() {
#Override
public List<Product> apply(Observable<List<Product>> products) throws Exception {
return (List<Product>) products;
}
}).toFlowable(BackpressureStrategy.BUFFER)

You need flatMapIterable:
return resource.flatMapIterable(list -> list)
.toFlowable(BackpressureStrategy.BUFFER)

Related

Android Room with RXJava2; onNext() of emitter is not properly triggered

I am switching from async tasks to rxjava2 and have some issues with my code tests.
I have a room table of elements that have a certain monetary amount. On a usercontrol that is called DisplayCurrentBudget, a sum of all amounts should be displayed. This number must refresh everytime a new element is inserted. I tackled the requirement in two ways, but both produce the same result: My code does not care if the database is updated, it only updates when the fragment is recreated (onCreateView).
My first attempt was this:
//RxJava2 Test
Observable<ItemS> ItemObservable = Observable.create( emitter -> {
try {
List<ItemS> movies = oStandardModel.getItemsVanilla();
for (ItemS movie : movies) {
emitter.onNext(movie);
}
emitter.onComplete();
} catch (Exception e) {
emitter.onError(e);
}
});
DisposableObserver<ItemS> disposable = ItemObservable.
subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribeWith(new DisposableObserver<ItemS>() {
public List<ItemS> BadFeelingAboutThis = new ArrayList<ItemS>();
#Override
public void onNext(ItemS movie) {
// Access your Movie object here
BadFeelingAboutThis.add(movie);
}
#Override
public void onError(Throwable e) {
// Show the user that an error has occurred
}
#Override
public void onComplete() {
// Show the user that the operation is complete
oBinding.DisplayCurrentBudget.setText(Manager.GetBigSum(BadFeelingAboutThis).toString());
}
});
I already was uncomfortable with that code. My second attempt produces the exact same result:
Observable<BigDecimal> ItemObservable2 = Observable.create( emitter -> {
try {
BigDecimal mySum = oStandardModel.getWholeBudget();
emitter.onNext(mySum);
emitter.onComplete();
} catch (Exception e) {
emitter.onError(e);
}
});
DisposableObserver<BigDecimal> disposable = ItemObservable2.
subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribeWith(new DisposableObserver<BigDecimal>() {
#Override
public void onNext(BigDecimal sum) {
// Access your Movie object here
oBinding.DisplayCurrentBudget.setText(sum.toString());
}
#Override
public void onError(Throwable e) {
// Show the user that an error has occurred
}
#Override
public void onComplete() {
// Show the user that the operation is complete
}
});
Any obvious issues with my code?
Thanks for reading, much appreciate it!
Edit:
I was asked what Manager.GetBigSum does, it actually does not do much. It only adds BigDecimal-Values of an Item list.
public static BigDecimal GetBigSum(List<ItemS> ListP){
List<BigDecimal> bigDList = ListP.stream().map(ItemS::get_dAmount).collect(Collectors.toList());
return bigDList.stream()
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
Further, I simplified the query. But it still does not care about DB updates, only about fragment recreation:
Single.fromCallable(() -> oStandardModel.getItemsVanilla())
.map(Manager::GetBigSum)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
e -> oBinding.DisplayCurrentBudget.setText(e.toString())
);
Your rx logic has no error. That should be internal error in your getWholeBudget.
But why you write rx so complex?
For your case, you can just write:
Single.fromCallable(() -> oStandardModel.getItemsVanilla())
.map(Manager::GetBigSum)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
e -> oBinding.DisplayCurrentBudget.setText(sum.toString()),
e -> log.error(e));
I solved it this way:
oStandardModel.getItemJointCatLive().observe(this, new Observer<List<ItemJointCat>>() {
#Override
public void onChanged(#Nullable final List<ItemJointCat> oItemSP) {
Single.fromCallable(() -> oStandardModel.getWholeBudget())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
e -> oBinding.DisplayCurrentBudget.setText(e.toString())
);
}
});
My mistake was that I assumed RXjava2 does not need an onchanged event...now i just use onchanged event of livedata observer to trigger a simple rxjava2 query.
Do you think there is anything wrong with that approach?

RxJava Single.concat

I have the following code:
model.getCategories()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<Category>>()
{
#Override
public void call(final List<Category> categories)
{
model.getUnits()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<Unit>>()
{
#Override
public void call(List<Unit> units)
{
view.showAddProductDialog(units, categories);
}
});
}
});
I have this ugly nesting. How can I fix it.
I tried something like this:
Single.concat(model.getCategories(), model.getUnits())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<? extends Object>>()
{
#Override
public void call(List<? extends Object> objects)
{
// do something
}
});
But the problem is that I cannot determinate whether it is List<Category> or List<Unit> comes.
Is there a way to use concat and detect what kind of stream comes (List<Category> or List<Unit> or something else) ?
Also I need to detect that all observers are completed to perform another action.
Thanks in advice.
Use Single.zip():
Single.zip(
getCategories().subscribeOn(Schedulers.io()),
getUnits().subscribeOn(Schedulers.io()),
(a, b) -> Pair.of(a, b)
)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
pair -> view.showAddProductDialog(pair.first, pair.second),
error -> showError(error.toString())
)
where Pair can be any tuple implementation, i.e., this.

Match or Join event and rule from two kafka topics in one datastream

i want to do join between two kafka topics in one Datastream.
In fact the two datastream must have the same id to make the join.
Event are the data coming from the sensors and rule contains rules that will be checked with the CEP(coming from User Interface).
Here is my test but it does not work, can anyone help me please ?
DataStream<Object> evtAndRule=inputEventStream.join(rulesStream)
.where(new KeySelector<TrackEvent, Object>() {
#Override
public Object getKey(Event event) throws Exception {
return event.getId();
}
}).equalTo(new KeySelector<RulesEvent, Object>() {
#Override
public Object getKey(RulesEvent rulesEvent) throws Exception {
return rulesEvent.getId();
}
}).window(TumblingTimeWindows.of(Time.of(10, TimeUnit.SECONDS)))
.apply(new FlatJoinFunction<TrackEvent, RulesEvent, Object>() {
#Override
public void join(TrackEvent trackEvent, RulesEvent rulesEvent, Collector<Object> collector) throws Exception {
....
}
});
I tried this but I do not know how to retrieve the desired rule and if this is the best solution
DataStream<Tuple2<Event , RulesEvent>> evtAndRule= inputEventStream.map(new MapFunction<Event , Tuple2<Event , RulesEvent>>() {
#Override
public Tuple2<Event , RulesEvent> map(final Event event) throws Exception {
return new Tuple2<Event , RulesEvent>(event, new RulesEvent());
}
});

Cannot resolve method 'subscribe(anonymous io.reactivex.functionx.Consumer<java.util.List<...>>)' in rxjava2?

after toList operator performs, original Flowable<<\List>> converts to Single<<\List>>. and it turns out if I create Consumer to subscribe to Single,
the Consumer value type cannot be changed except Object?
#Override
public void loadBannerData(final ADFilterType adFilterType) {
remoteListDataSource.getBannerListData(adFilterType)
.flatMap(new Function<List<BannerBeanList.BannerBean>, Publisher<?>>() {
#Override
public Publisher<?> apply(List<BannerBeanList.BannerBean> bannerBeen) throws Exception {
return Flowable.fromIterable(bannerBeen);
}
})
.toList()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
/******************************Consume Value Type**************************
.subscribe(new Consumer<List<BannerBeanList.BannerBean>>() {
#Override
public void accept(List<BannerBeanList.BannerBean> bannerBeens) throws Exception {
mainTabView.showMainBanner(bannerBeens);
}
});
*****************************************************************************/
}
From my comment: this happens because you have Publisher<?> instead of Publisher<BannerBeanList.BannerBean> in your code. Often IDEs can't infer types of lambdas or functional interfaces and you'll end up with ? or Object as their type when using some generate/convert refactoring function.

public void onSuccess(String result), from where/how the result is being set?

I've tried to follow the GWT RPC sample codes, and i don't understand how the AsyncCallback's Onsuccess method result is being set. Anyone help me to understand the flow.
Thanks.
AsyncCallback<YourReturnType> callback = new AsyncCallback<YourReturnType>() {
#Override
public void onSuccess(YourReturnType result) {
//to do something with the result
}
#Override
public void onFailure(Exception ex) {
//to do something with exceptions
}
}
#Rajesh, I'm providing a link here. I hope this may help you.