I've been adapting my Android app to use RxJava but I'm having a little bit of trouble doing so. As I had been advised in a previous post (Wait for all requests in Android Volley), I'm using Observables to mimic how I'm interfacing with my REST API in JavaScript. Specifically, using the promise library, I compose calls like this:
$q.all([
fetchResourceA(),
fetchResourceB()
])
.then(function (responses) {
...
return fetchResourceC();
})
.then(function (response) {
...
});
In this example, I query two resources simultaneously, collect the results, then collect a third resource based on some of the parameters from the previously collected resources. The best I've been able to do to mimic this in RxJava is like this:
Observable o = Observable.zip(
fetchResourceA(),
fetchResourceB(),
new Func2<ResA, ResB, Object>() {
#Override
public Object call(ResA resA, ResB resB) {
...
}
}
);
But I'm struggling to compose them like I did in JavaScript. Do I need to simply create a second observable and subscribe to it in the callback of the zip? That's what I'm doing now, and it works, but I'd like to know if there's a more elegant and more reactive-appropriate way to structure my requests.
The .then method from promise can be transposed to flatMap method in RxJava
So, what you can do, is to zip then flatMap then flatMap
Observable.zip(fetchA(), fetchB(), (a, b) -> new Response(a, b))
.flatMap((responses) -> fetchC())
.flatMap((cResponse) -> /* whatever */)
.subscribe();
Please note that fetchA(), fetchB(), fetchC() return Observables.
(My example use lambdas for clarity)
Related
I want to use coroutine in my kotlin app for must of it. but this app depends a lot on a service which return rxjava2 type object (so our input will be all the rxjava type). How can we still use coroutine in this model app instead of rxjava2. should we create a layer only convert rxjava object to normal object (or coroutine object?). or can we use both two together like:
SomeObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { value->
viewmodelScope.launch{
// send a flow or coroutine suspend fonction with value
}
},
Thanks,
You could wrap the RxJava functions with suspend functions.
See https://github.com/Kotlin/kotlinx.coroutines/issues/869
I want to answer my own question, It's not a good approche to use flow and rx at the same time. because it resolves the same problem. Rxjava + livedata is a clean architecture to go. or just use flow. so for resume:
Rxjava + livedata (a little bit coroutine to do some general
operation)
flow + coroutine
Two clean ways to make a good architecture. so if I have already rx type there is no need to convert to flow and reuse.
I'm quite new to reactive programming and I've introduced myself to RxJava2 in Android. For the time being, I've faced easy problems, such as zipping observables. But now, something new cropped up, I'm trying to explain.
Suppose I've got a list of requests Observable<List<Request>>. What I want to do is to call a web service which returns per each request, the list of routes (wrapped in an Observable). I've checked questions like this, but in this case I think I can't flatMap an observable and a list of observables.
How can I do it? Is there any other operator?
You can flatten the Observable<List<Request>> into Observable<Request> using flatMapIterable. Assuming you have a helper method with the signature Observable<List<Route>> getListOfRoutes(Request request) { ... } you can do this:
Observable<List<Request>> obs = ...;
obs.flatMapIterable(l -> l)
.flatMap(request -> getListOfRoutes(request)
.doOnNext(routes -> request.setRoutes(routes))
.map(ign -> request)
)
...
This is assuming that you ultimately want Observable<Request> to be emitted downstream. If you want a different type, you can do something different in the map operator to suit your needs.
I'm refactoring the implementation of my repositories using RxJava so i want to know some ways to edit, for example, a user.
My getUser(email: String), with email as id, is returning an observable and in the repository implementation i either get the data from database or server, all good by now.
What i want to achieve is editing a user. For that i would have and update(user: User) function, and the naive way to use it would be
userRepository.getUser(email)
.subscribeOn(Schedulers.io())
.subscribe { user ->
user.name = "antoher name"
userRepository.update(user)
.subscribeOn(Schedulers.io())
.subscribe {
//handle response
}
}
Is there a way to avoid this type of call of an observer inside an observer? It is not very readable for me and i guess there's a better way but i'm not getting it.
NOTE: I'm using clean architecture, so i think an update for every field, making me get user in data module is not correct as i would have subscribe to an observer in data, and that difficult the dispose when activity destroys
For me is not the same question as When do you use map vs flatMap in RxJava? because, despite of flatMap being the thing that answer the question, it is not the same question, so anyone who has the same problem/question but don't know that flatmap is the answer, will never reach to use flatmap.
One strength of using RxJava is that you can chain as many async operations (method that would return Observable or Single, repository methods in your case) as you want without falling into callback hells. You see in your code that there are nested subscribe blocks. What if you had to chain more async network operations? You fall into callback hells and the code will become harder to follow and maintain.
Removing nested callbacks and making code more functional, compositional, and readable is one thing RxJava is really good at. In the intro part of ReactiveX website , they mention about this in the intro part of ReactiveX website (http://reactivex.io/intro.html).
Callbacks solve the problem of premature blocking on Future.get() by
not allowing anything to block. They are naturally efficient because
they execute when the response is ready.
But as with Futures, while callbacks are easy to use with a single
level of asynchronous execution, with nested composition they become
unwieldy.
Flatmap operator is to the rescue here. You can look into the definition of flatMap operator in the link below.
http://reactivex.io/documentation/operators/flatmap.html
Below is the code I would use in your case.
userRepository.getUser(email)
.subscribeOn(Schedulers.io())
.map { user -> user.name = "another name"; return user; }
.flatMap { user -> userRepository.update(user) }
.doOnSuccess { /* handle response here */ } // doOnNext if you are using observable
.subscribe({ /* or handle response here */ }, { /* must handle error here */})
Flatmap operator flattens Single of update response which will be returned by your repository's update method and pass just the response downstream. Above code is not only easier to read but also makes your code reusable because update logic is now part of the chain.
Distinguishing between map and flatMap is really important in exploiting the full benefit of RxJava so it will be really beneficial to get used to it!
I am working on an application, where I had used Rx-android and Retrofit to do the network request, but now there is a requirement in the project where I have to do the nested network calls.I tried to google it out but didn't found any good article.If any one has worked on such topic then please let me know your findings.
Assuming you're using retrofit with the rxjava adapter:
fun firstRequest(): Single<Response<String>>
fun secondRequest(idFromFirstRequest: String): Single<Response<ResponseBody>>
Use flatmap operator to chain the network calls:
firstRequest()
// do more operators on the request, like transforming the object, or showing it first on the ui
.flatMap { stringId -> secondRequest(stringId) }
// you can flatMap here again to chain another network requests
// .flatMap { thirdRequest() }
// .flatMap { fourthRequest() }
// and so on...
There are various articles related to API chaining, and the easiest way to achieve is using Rx-Java approaches
1) Using RxJava Zip operator (for parallel requests)
2) Using RxJava flatMap() operator(To request serially one after another)
Refer these two links for more detail examples
Synchronizing Network Calls With RxJava
Multiple api request using retrofit and rx java
I'm new to RxJava, often got confused by flatMap function. According to the doc, flatmap transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable
Can someone give a good use case for it? Why transform the original Observable into Observables (plural) then turn them into a single Observable.
Why don't you just use 'map'?
If you give an example in Android that's awesome, otherwise plain Java is good enough. Thanks
I see tag Android on your question. So, probably you should be familiar with Retrofit.
Let's image that you have 2 methods:
public interface FoxreyRestApi {
#POST("/signin")
Observable<SignInResponse> signin(#Body SignInRequest request);
#GET("/user")
Observable<User> getUser(String accessToken);
}
You want to get user data, but you need accessToken, which return is SignInResponse.
You can do this:
1). Create your RestAdapter.
2). Do queries one - after - another:
restAdapter.signin(request)
.flatMap(r -> restAdapter.getUser(r.getAccessToken()))
.subscribe(user -> {/*User your user*/});
Let's say you have an
Observable<Foo> fooObservable;
And you want to call another method which takes a Foo and emits an Observable<Bar>
Something like:
public Observable<Bar> getBars(Foo foo);
If you did:
fooObservable.map(foo -> getBars(foo));
You'd end up with an Observable<Observable<Bar>> because you've transformed your Foo -> Observable<Bar> which is probably not what you want.
Instead you can use flatMap which "flattens the observable":
Observable<Bar> barObservable = fooObservable.flatMap(foo -> getBars(foo));
Very often I use it to transform some of the UI events to observable background tasks:
ViewObservable.clicks(calculateBtn)
.flatMap(new Func1<OnClickEvent, Observable<Integer>>() {
#Override
public Observable<Integer> call(OnClickEvent onClickEvent) {
return observeBackgroundOperation()
.observeOn(AndroidSchedulers.mainThread())//interaction with UI must be performed on main thread
.doOnError(new Action1<Throwable>() {//handle error before it will be suppressed
#Override
public void call(Throwable throwable) {
progress.setVisibility(View.GONE);
calculateBtn.setEnabled(true);
Toast.makeText(IOCombineSampleActivity.this, R.string.mix_error_message, Toast.LENGTH_SHORT).show();
}
})
.onErrorResumeNext(Observable.<Integer>empty());//prevent observable from breaking
}
})
.subscribe(new Action1<Integer>() {...});
Because it's easy to define background operations using observable, I used flatMap to transform button click events to 'something done in background events' (for example network request finished with Retrofit) and then observe them.
Note, that observable in flatMap can emit single value, which is done in sample.
This way I have declaratively defined interaction between UI and background processes.
I handle errors with doOnError and then use onErrorResumeNext(Observable.<Integer>empty()) to prevent observable from terminating with onError. Because I use flatMap, my observable is not completed (while inner flatMap was) and is waiting for next click events.
Full sample of code you can find in my article.