What is the difference between subscribe() and subscribeWith() in RxJava2 in android? Both function are used to subscribe an Observer on an Observable. What is the major difference between the two function ?.
Where to use subscribe and where to use subscribeWith. If possible please provide code samples.
Since 1.x Observable.subscribe(Subscriber) returned Subscription, users often added the Subscription to a CompositeSubscription for example:
CompositeSubscription composite = new CompositeSubscription();
composite.add(Observable.range(1, 5).subscribe(new TestSubscriber<Integer>()));
Due to the Reactive-Streams specification, Publisher.subscribe returns void and the pattern by itself no longer works in 2.0. To remedy this, the method E subscribeWith(E subscriber) has been added to each base reactive class which returns its input subscriber/observer as is. With the two examples before, the 2.x code can now look like this since ResourceSubscriber implements Disposable directly:
CompositeDisposable composite2 = new CompositeDisposable();
composite2.add(Flowable.range(1, 5).subscribeWith(subscriber));
Source: What's different in [RxJava] 2.0
Related
I am building an Android MVVM application using RxJava2. What I want is to expose an Observable in my ViewModel, which I also can receive the last emitted value (like a BehaviourSubject). I don't want to expose a BehaviourSubject because I don't want the View to be able to call onNext().
For example, in my ViewModel I expose a date. I now want to subscribe a TextView to changes, but I also need to be able to access the current value if I want to show a DatePickerDialog with this date as initial value.
What would be the best way to achieve this?
Delegate:
class TimeSource {
final BehaviorSubject<Long> lastTime = BehaviorSubject.createDefault(
System.currentTimeMillis());
public Observable<Long> timeAsObservable() {
return lastTime;
}
public Long getLastTime() {
return lastTime.getValue();
}
/** internal only */
void updateTime(Long newTime) {
lastTime.onNext(newTime);
}
}
I don't want to expose a BehaviourSubject
Subject, by definition, is "an Observer and an Observable at the same time". Therefore, instead of exposing BehaviorSubject itself just expose Observable, thus client (in this case the view) won't be able to perform onNext(), but will be able to receive last emitted value.
As an alternative to subject approach you can use replay(1).autoConnect() approach. See more details concerning this approach in "RxJava by example" presentation by Kaushik Gopal.
Also, consider cache() operator (see difference of cache and replay().autoConnect() here).
Is there a concept of using promises in java (just like ut is used in JavaScript) instead of using nested callbacks ?
If so, is there an example of how the callback is implemented in java and handlers are chained ?
Yep! Java 8 calls it CompletableFuture. It lets you implement stuff like this.
class MyCompletableFuture<T> extends CompletableFuture<T> {
static final Executor myExecutor = ...;
public MyCompletableFuture() { }
public <U> CompletableFuture<U> newIncompleteFuture() {
return new MyCompletableFuture<U>();
}
public Executor defaultExecutor() {
return myExecutor;
}
public void obtrudeValue(T value) {
throw new UnsupportedOperationException();
}
public void obtrudeException(Throwable ex) {
throw new UnsupportedOperationException();
}
}
The basic design is a semi-fluent API in which you can arrange:
(sequential or async)
(functions or actions)
triggered on completion of
i) ("then") ,or ii) ("andThen" and "orThen")
others. As in:
MyCompletableFuture<String> f = ...; g = ...
f.then((s -> aStringFunction(s)).thenAsync(s -> ...);
or
f.andThen(g, (s, t) -> combineStrings).or(CompletableFuture.async(()->...)....
UPDATE 7/20/17
I wanted to edit that there is also a Library called "ReactFX" which is supposed to be JavaFX as a reactive framework. There are many Reactive Java libraries from what I've seen, and since Play is based on the Reactive principal, I would assume that these Reactive libraries follow that same principal of non-blocking i/o, async calls from server to client and back while having communication be send by either end.
These libraries seem to be made for the client side of things, but there might be a Server reactive library as well, but I would assume that it would be wiser to use Play! with one of these client side reactive libraries.
You can take a look at https://www.playframework.com/
which implements this functionality here
https://www.playframework.com/documentation/2.2.0/api/java/play/libs/F.Promise.html
Additonal reading https://www.playframework.com/documentation/2.5.x/JavaAsync
Creating non-blocking actions
Because of the way Play works, action code must be as fast as possible, i.e., non-blocking. So what should we return from our action if we are not yet able to compute the result? We should return the promise of a result!
Java 8 provides a generic promise API called CompletionStage. A CompletionStage<Result> will eventually be redeemed with a value of type Result. By using a CompletionStage<Result> instead of a normal Result, we are able to return from our action quickly without blocking anything. Play will then serve the result as soon as the promise is redeemed.
The web client will be blocked while waiting for the response, but nothing will be blocked on the server, and server resources can be used to serve other clients.
How to create a CompletionStage
To create a CompletionStage<Result> we need another promise first: the promise that will give us the actual value we need to compute the result:
CompletionStage<Double> promiseOfPIValue = computePIAsynchronously();
CompletionStage<Result> promiseOfResult = promiseOfPIValue.thenApply(pi ->
ok("PI value computed: " + pi)
);
Play asynchronous API methods give you a CompletionStage. This is the case when you are calling an external web service using the play.libs.WS API, or if you are using Akka to schedule asynchronous tasks or to communicate with Actors using play.libs.Akka.
A simple way to execute a block of code asynchronously and to get a CompletionStage is to use the CompletableFuture.supplyAsync() helper:
CompletionStage<Integer> promiseOfInt = CompletableFuture.supplyAsync(() -> intensiveComputation());
Note: It’s important to understand which thread code runs on which promises. Here, the intensive computation will just be run on another thread.
You can’t magically turn synchronous IO into asynchronous by wrapping it in a CompletionStage. If you can’t change the application’s architecture to avoid blocking operations, at some point that operation will have to be executed, and that thread is going to block. So in addition to enclosing the operation in a CompletionStage, it’s necessary to configure it to run in a separate execution context that has been configured with enough threads to deal with the expected concurrency. See Understanding Play thread pools for more information.
It can also be helpful to use Actors for blocking operations. Actors provide a clean model for handling timeouts and failures, setting up blocking execution contexts, and managing any state that may be associated with the service. Also Actors provide patterns like ScatterGatherFirstCompletedRouter to address simultaneous cache and database requests and allow remote execution on a cluster of backend servers. But an Actor may be overkill depending on what you need.
Async results
We have been returning Result up until now. To send an asynchronous result our action needs to return a CompletionStage<Result>:
public CompletionStage<Result> index() {
return CompletableFuture.supplyAsync(() -> intensiveComputation())
.thenApply(i -> ok("Got result: " + i));
}
Actions are asynchronous by default
Play actions are asynchronous by default. For instance, in the controller code below, the returned Result is internally enclosed in a promise:
public Result index() {
return ok("Got request " + request() + "!");
}
Note: Whether the action code returns a Result or a CompletionStage<Result>, both kinds of returned object are handled internally in the same way. There is a single kind of Action, which is asynchronous, and not two kinds (a synchronous one and an asynchronous one). Returning a CompletionStage is a technique for writing non-blocking code.
Some info on CompletionStage
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html
which is a subclass of the class mentioned in #Debosmit Ray's answer called CompletableFuture
This Youtube Video by LinkedIn dev Mr. Brikman explains a bit about Promises in
https://youtu.be/8z3h4Uv9YbE?t=15m46s
and
https://www.youtube.com/watch?v=4b1XLka0UIw
I believe the first video gives an example of a promise, the second video might also give some good info, I don't really recall which video had what content.
Either way the information here is very good, and worth looking into.
I personally do not use Play, but I have been looking at it for a long, long time, as it does a lot of really good stuff.
If you want to do Promise even before Java7, "java-promise" may be useful. (Of course it works with Java8)
You can easily control asynchronous operations like JavaScript's Promise.
https://github.com/riversun/java-promise
example
import org.riversun.promise.Promise;
public class Example {
public static void main(String[] args) {
Promise.resolve("foo")
.then(new Promise((action, data) -> {
new Thread(() -> {
String newData = data + "bar";
action.resolve(newData);
}).start();
}))
.then(new Promise((action, data) -> {
System.out.println(data);
action.resolve();
}))
.start();
System.out.println("Promise in Java");
}
}
result:
Promise in Java
foobar
Using MongoDB, I need to persist objects from Twitter4J. Twitter4J uses interfaces, which are implemented in JSON versions. Example:
The API returns Status (an interface), and Status is implemented as StatusJSONImpl.
I can't save Status to MongoDB, I need to implement StatusJSONImpl.
My issue is, this class StatusJSONImpl is not public (see here) so I can't use it in my code. I tried to download the source of Twitter4J to manually add "public" to StatusJSONImpl: I can do:
Status status = twitter.updateStatus(latestStatus);
String statusStringified = TwitterObjectFactory.getRawJSON(status);
StatusJSONImpl statusImplemented = (StatusJSONImpl) TwitterObjectFactory.createUserList(statusStringified);
SingletonLaunchDB.getMongo().save(statusImplemented);
But I still get a java.lang.IllegalAccessError on the class StatusJSONImpl at run time.
I see from other SA answers that users routinely point other users to this Impl classes... how do they do to use it in their code?
Your help is much appreciated.
Status is serializable. To recover StatusJSONImpl from statusStringified you can write.
JSONObject json = new JSONObject(statusStringified);
Status status = new StatusJSONImpl(json);
The code sample is from StatusSerializationTest.java
I hope this helps.
Use the static factory method on TwitterObjectFactory:
Status status = TwitterObjectFactory.createStatus(statusAsString);
StatusJSONImpl is an implementation detail which library users are not meant deal with. The only thing a user of the library should care about is the contract (the Status interface in this case) which is necessarily public and the library authors promise to fulfill. On the other hand, the concrete classes like StatusJSONImpl are not public on purpose in order to prevent consumers from using them and getting tightly coupled to a specific implementation which may change over time. And from the authors' point of view, by coding to an interface they are then free to return any concrete type they wish as long as it fulfills the contract.
If you check the class that is returned from the factory method, it is StatusJSONImpl. But to reiterate, as a user of the library you should need to know or care about that.
Status status = TwitterObjectFactory.createStatus(statusAsString);
status.getClass(); // class twitter4j.StatusJSONImpl
To understand more about why this is done, you can read about static factory methods.
This could get a little bit complicated and I'm not that experienced with Observables and the RX pattern so bear with me:
Suppose you've got some arbitrary SDK method which returns an Observable. You consume the method from a class which is - among other things - responsible for retrieving data and, while doing so, does some caching, so let's call it DataProvider. Then you've got another class which wants to access the data provided by DataProvider. Let's call it Consumer for now. So there we've got our setup.
Side note for all the pattern friends out there: I'm aware that this is not MVP, it's just an example for an analogous, but much more complex problem I'm facing in my application.
That being said, in Kotlin-like pseudo code the described situation would look like this:
class Consumer(val provider: DataProvider) {
fun logic() {
provider.getData().subscribe(...)
}
}
class DataProvider(val sdk: SDK) {
fun getData(): Consumer {
val observable = sdk.getData()
observable.subscribe(/*cache data as it passes through*/)
return observable
}
}
class SDK {
fun getData(): Observable {
return fetchDataFromNetwork()
}
}
The problem is, that upon calling sdk.subscribe() in the DataProvider I'm already triggering the Observable's subscribe() method which I don't want. I want the DataProvider to just silently listen - in this example the triggering should be done by the Consumer.
So what's the best RX compatible solution for this problem? The one outlined in the pseudo code above definitely isn't for various reasons one of which is the premature triggering of the network request before the Consumer has subscribed to the Observable. I've experimented with publish().autoComplete(2) before calling subscribe() in the DataProvider, but that doesn't seem to be the canonical way to do this kind of things. It just feels hacky.
Edit: Through SO's excellent "related" feature I've just stumbled across another question pointing in a different direction, but having a solution which could also be applicable here namely flatMap(). I knew that one before, but never actually had to use it. Seems like a viable way to me - what's your opinion regarding that?
If the caching step is not supposed to modify events in the chain, the doOnNext() operator can be used:
class DataProvider(val sdk: SDK) {
fun getData(): Observable<*> = sdk.getData().doOnNext(/*cache data as it passes through*/)
}
Yes, flatMap could be a solution. Moreover you could split your stream into chain of small Observables:
public class DataProvider {
private Api api;
private Parser parser;
private Cache cache;
public Observable<List<User>> getUsers() {
return api.getUsersFromNetwork()
.flatMap(parser::parseUsers)
.map(cache::cacheUsers);
}
}
public class Api {
public Observable<Response> getUsersFromNetwork() {
//makes https request or whatever
}
}
public class Parser {
public Observable<List<User>> parseUsers(Response response) {
//parse users
}
}
public class Cache {
public List<User> cacheUsers(List<User> users) {
//cache users
}
}
It's easy to test, maintain and replace implementations(with usage of interfaces). Also you could easily insert additional step into your stream(for instance log/convert/change data which you receive from server).
The other quite convenient operator is map. Basically instead of Observable<Data> it returns just Data. It could make your code even simpler.
The features mentioned in title serve a simple purpose: allow an user to bind some event listeners to an object which will dispatch all event listeners when event occurs.
This simple concept can, of course, achieved like this:
public class EventEmitter extends ArrayList<Runnable>;
But I would prefer a smarter emitter - ideally one that allows arguments to be passed to the callback. Runnable does not have any arguments of course. Lambda expressions do have parameters on the other side.
Smart emitters allow you to define specific callback parameters:
EventEmitter<String, Boolean> emitter = new EventEmitter();
My question whether this thing is part of java library or if I have to implement it myself. On google, I only found some java.awt.AWTEvent but that is not event dispatcher.
My preferred pseudo code:
// Requires lambdas with (File, int) signature
public final EventEmitter<File, int> downloadCompleteEvent;
And new events added as:
downloaderClass.downloadCompleteEvent
.addListener(
(File file, int downloadTime)->System.out.println("Downloaded "+file.getAbsolutePath()+" in "+downloadTime+" seconds.")
);
And dispatch events as:
this.downloadCompleteEvent.dispatch(downloadedFile, elapsedTime);
In pure Java, you can use a CompletableFuture which represents a state or a work currently in action. On a completable future, you can add one or more listeners which will be invoked with result.
by example:
public CompletableFuture<DownloadResult> download() {
// computing a result async
CompletableFuture<DownloadResult> future = CompletableFuture.supplyAsync(/* your process*/);
return future;
}
future.thenAccept( (DownloadResult) r -> { ... } );
// will be called when process is done
Also, you can be interested by EventBus into Guava library: https://github.com/google/guava/wiki/EventBusExplained
Or by RXJava library: https://github.com/ReactiveX/RxJava/wiki/How-To-Use-RxJava
Some libraries may have a class that can be extended to add this functionality, but it is not a native java idiom. If you want this functionality you need to track and notify event listeners yourself via the observer pattern.