I was reading a tutorial:
http://code.tutsplus.com/tutorials/getting-started-with-reactivex-on-android--cms-24387
which concers RxAndroid in particular but it's pretty much the same as in RxJava. I am not sure that I understood the concept completely.
Below I have written a method and then a sample usage.
My question is: is this the right way to implement my functions so that I can run them on other threads asynchronously? They will in fact only return a created Observable running the real code, and handling errors and all that stuff.
Or is this wrong, then I'd like to know the correct way.
Observable<String> googleSomething(String text){
return Observable.create(new Observable(){
#Override
public void call(Subscriber<? super String> subscriber) {
try {
String data = fetchData(text); // some normal method
subscriber.onNext(data); // Emit the contents of the URL
subscriber.onCompleted(); // Nothing more to emit
} catch(Exception e) {
subscriber.onError(e); // In case there are network errors
}
}
});
}
googleSomething("hello world").subscribeOn(Schedulers.io()).observeOn(Schedulers.immediate()).subscribe(...)
Also is Schedulers.immediate() used in order to execute the subscriber code on the current thread? It says "Creates and returns a Scheduler that executes work immediately on the current thread." in javadoc, but I'm not sure.
Unless you are more experienced and need a custom operator or want to bridge a legacy addListener/removeListener based API you should not start with create. There are several questions on StackOverflow which used create and was the source of trouble.
I'd prefer fromCallable which let's you generate a single value or throw an Exception thus no need for those lengthy defer + just sources.
Schedulers.immediate() executes its task immediately on the caller's thread, which is the io() thread in your example, not the main thread. Currently, there is no support for moving back the computation to the Java main thread as it requires blocking trampolining and usually a bad idea anyway.
You should almost never use create(), especially not as a beginner. There are easier ways to create observables, and create() is difficult to implement correctly.
Most of the time, you can easily get around create() by using defer(). E.g., in this case you'd do:
Observable<String> googleSomething(String text) {
return Observable.defer(new Func0<Observable<String>>() {
#Override
public Observable<String> call() {
try {
return Observable.just(fetchData(text));
} catch (IOException e) {
return Observable.error(e);
}
}
});
}
If you're not using a checked exception, then you could even get rid of the try-catch. RxJava will automatically forward any RuntimeException to the onError() part of the subscriber.
You can create Observable via Observable.create(new OnSubscribe {}) method however:
Look at defer() operator, which allows you to return for example Observable.just() and Observable.error() so you don't need to touch subscriber directly
Prefer using SyncOnSubscribe/AsyncOnSubscribe to handle backpressure
Schedulers.immediate() will keep Observable processing on the thread it already is - so in your case it will be one of the Schedulers.io threads
Your code looks good to me. If you are unsure wether that is running on another thread or not. you could print something immediately after you call .subscribe() and see the order of the outputs.
googleSomething("hello world").subscribeOn(Schedulers.io()).observeOn(Schedulers.immediate()).subscribe(...)
System.out.println("This should be printed first");
Try to simulate a long running operation inside fetchData() and print something else immediately afterwards. As .subscribe() is non blocking "This should be printed first" is in fact, going to be printed first.
Alternatively, you can print the current thread using.
Thread.currentThread().getName()
Use this inside and outside your observable and the outputs should differ.
Related
I still do not understand when to apply this method. In fact, it is similar to Mono.just, but I heard that callback is used for heavy operations if it needs to be performed separately from other flows. Now I use it like this, but is it correct.
Here is an example of use, I wrap sending a firebase notification in a callback since the operation is long
#Override
public Mono<NotificationDto> sendMessageAllDevice(NotificationDto notification) {
return Mono.fromCallable(() -> fcmProvider.sendPublicMessage(notification))
.thenReturn(notification);
}
maybe I still had to wrap up here in Mono.just ?
It depends which thread you want fcmProvider.sendPublicMessage(...) to be run on.
Either the one currently executing sendMessageAllDevice(...):
T result = fcmProvider.sendPublicMessage(notification);
return Mono.just(result);
Or the one(s) the underlying mono relies on:
Callable<T> callable = () -> fcmProvider.sendPublicMessage(notification);
return Mono.fromCallable(callable);
I would guess you need the latter approach.
If you use Mono.just(computeX()), computeX() is called immediately. No want you want(I guess).
If you use Mono.fromCallable(() -> computeX()), the computation is still not performed. I mean computeX() is only called when you subscribe to it. Maybe using .map, .flatMap, etc.
Important: if computeX() return Mono you doe not need to use Mono.fromCallable. It's only for blocking code
As you explained in the description, Mono.fromCallable is used when you want to compute a result with an async execution (mostly some heavy operation).
Since, you have already generated the Mono with Mono.fromCallable you do not have to wrap it again with Mono.just.
I am using Java8. I have an Listener that calls onSuccess when completed with a customToken.
#Override
public String getCustomToken(Person person) {
FirebaseAuth.getInstance().createCustomToken(person.getUid()).addOnSuccessListener(new OnSuccessListener<String>() {
#Override
public void onSuccess(String customToken) {
// I would like to return the customToken
}
});
return null;
}
Question
How do I get this method to return the String customToken?
Your question is intriguing, but the accepted answer unfortunately provides you with wrong means.
The problem with your question is that of API. You are trying to use callbacks in a way they are not designed to be used. A callback, by definition, is supposed to provide a means to do something asynchronously. It is more like a specification of what to do when something happens (in future). Making a synchronous method like getCustomToken() return something that is a result of an inherently asynchronous operation like onSuccess() implies a fundamental disconnect.
While dealing with callbacks, it is critical to understand the importance of continuations: taking actions when certain events of interest happen. Note that these events may not even happen. But you are specifying in the code the actions to take, if and when those events occur. Thus, continuation style is a shift from procedural style.
What adds to the data flow complexity is the syntax of the anonymous inner classes. You tend to think "oh, why can't I just return from here what onSuccess() returns? After all, the code is right here." But imagine that Java had no inner classes (and as you may know, (anonymous) inner class can easily be replaced by a class that is not an inner class). You'd have needed to do something like:
OnSuccessListener listener = new SomeImplementation();
FirebaseAuth.getInstance().createCustomToken(listener);
Now, the code that returned data (String) is gone. You can even visually reason that in this case, there is no way for your method to return a string -- it is simply not there!
So, I encourage you to think of what should happen if and when (in future) onSuccess() is called on the OnSuccessListener instance that you pass in. In other words, think twice if you really want to provide in your API, the getCustomToken() method (that returns a token string, given a Person instance).
If you absolutely must provide such a method, you
Should document that the returned token may be null (or something more meaningful like None) and that your clients must try again if they want a valid value.
Should provide a listener that updates a thread-safe container of tokens that this method reads.
Googling around, I found the Firebase documentation. This also seems to suggest taking an action on success (in a continuation style):
FirebaseAuth.getInstance().createCustomToken(uid)
.addOnSuccessListener(new OnSuccessListener<String>() {
#Override
public void onSuccess(String customToken) {
// **Send token back to client**
}
});
The other problem with trying to provide such API is the apparent complexity of the code for something trivial. The data flow has become quite complex and difficult to understand.
If blocking is acceptable to you as a solution, then perhaps you can use the Callable-Future style where you pass a Callable and then later do a get() on the Future that may block. But I am not sure if that is a good design choice here.
This would work syntactically:
final List<String> tokenContainer = new ArrayList<>();
FirebaseAuth.getInstance().createCustomToken(person.getUid()).addOnSuccessListener(new OnSuccessListener<String>() {
#Override
public void onSuccess(String customToken) {
tokenContainer.add(customToken);
}
});
return tokenContainer.get(0);
As said; this works syntactically. But if it really works would depend if the overall flow is happening in one thread; or multiple ones.
In other words: when the above code is executed in sequence, then that list should contain exactly one entry in the end. But if that callback happens on a different thread, then you would need a more complicated solution. A hackish way could be to prepend
return tokenContainer.get(0);
with
while (tokenContainer.isEmpty()) {
Thread.sleep(50);
}
return tokenContainer.get(0);
In other words: have the "outer thing" sit and wait for the callback to happen. But the more sane approach would be to instead use a field of the surrounding class.
Edit: if the above is regarded a hack or not; might depend on your context to a certain degree. The only thing that really troubles me with your code is the fact that you are creating a new listener; which gets added "somewhere" ... to stay there?! What I mean is: shouldn't there be code to unregister that listener somewhere?
The original accepted answer suggests sleeping the thread, which is a bad solution because you can't know how long the thread needs to sleep. A better solution is to use a semaphore (or similarly, a latch). After the listener gets the value, it releases a semaphore, which allows your thread to return the value, as shown below.
private final AtomicReference<String> tokenReference = new AtomicReference();
private final Semaphore semaphore = new Semaphore(0);
public String getCustomToken(Person person) {
FirebaseAuth.getInstance().createCustomToken(person.getUid()).addOnSuccessListener(customToken -> {
this.tokenReference.set(customToken);
this.sempahore.release();
});
this.semaphore.acquire();
return this.tokenReference.get();
}
Notice also that I used an AtomicReference because in order for what you asked for to be possible at all the listener must be called on a separate thread than the thread on which getCustomToken was called, and we want the value to be synchronized (I'd guess that behind the scenes Firebase is creating a thread, or this call occurs over the network). Since this.tokenReference will be overwritten, it is possible to get a newer value when getCustomToken is called more than once, which may or may not be acceptable depending on your use case.
Extract a variable into a suitable scope (class attribute or method variable)
private String customToken;
#Override
public String getCustomToken(Person person) {
FirebaseAuth.getInstance().createCustomToken(person.getUid()).addOnSuccessListener(new OnSuccessListener<String>() {
#Override
public void onSuccess(String customToken) {
this.customToken = customToken
}
});
return null;
}
I've got a question about CompletableFuture and its possible usage for lazy computations.
It seems like it is a great substitute for RunnableFuture for this task since it is possible to easily create task chains and to have total control of each chain link. Still I found that it is very hard to control when exactly does the computation take place.
If I just create a CompletableFuture with supplyAssync method or something like that, it is OK. It waits patiently for me to call get or join method to compute. But if I try to make an actual chain with whenCompose, handle or any other method, the evaluation starts immediately, which is very frustrating.
Of course, I can always place some blocker task at the start of the chain and release the block when I am ready to begin calculation, but it seems a bit ugly solution. Does anybody know how to control when does CompletableFuture actually run.
CompletableFuture is a push-design, i.e. results are pushed down to dependent tasks as soon as they become available. This also means side-chains that are not in themselves consumed still get executed, which can have side-effects.
What you want is a pull-design where ancestors would only be pulled in as their data is consumed.
This would be a fundamentally different design because side-effects of non-consumed trees would never happen.
Of course with enough contortions CF could be made to do what you want, but you should look into the fork-join framework instead which allows you to only run the computations you depend on instead of pushing down results.
There's a conceptual difference between RunnableFuture and CompletableFuture that you're missing here.
RunnableFuture implementations take a task as input and hold onto it. It runs the task when you call the run method.
A CompletableFuture does not hold onto a task. It only knows about the result of a task. It has three states: complete, incomplete, and completed exceptionally (failed).
CompletableFuture.supplyAsync is a factory method that gives you an incomplete CompletableFuture. It also schedules a task which, when it completes, will pass its result to the CompletableFuture's complete method. In other words, the future that supplyAsync hands you doesn't know anything about the task, and can't control when the task runs.
To use a CompletableFuture in the way you describe, you would need to create a subclass:
public class RunnableCompletableFuture<T> extends CompletableFuture<T> implements RunnableFuture<T> {
private final Callable<T> task;
public RunnableCompletableFuture(Callable<T> task) {
this.task = task;
}
#Override
public void run() {
try {
complete(task.call());
} catch (Exception e) {
completeExceptionally(e);
}
}
}
A simple way of dealing with your problem is wrapping your CompletableFuture in something with a lazy nature. You could use a Supplier or even Java 8 Stream.
it is late, but how about using constructor for first CompletableFuture in the chain?
CompletableFuture<Object> cf = new CompletableFuture<>();
// compose the chain
cf.thenCompose(sometask_here);
// later starts the chain with
cf.complete(anInputObject);
Upon pre-submission review, I realize this question might be incredibly silly.
if (this.gameOver(gpos) > 0) {
//do stuff
return this.gameOver(gpos);
}
Compare
if (this.gameOver()) {
//do stuff
return this.gameOver(gpos);
}
I was in doubt as to whether or not the first example would call this.gameOver(gpos); twice or just once at the beginning. Obviously, it does call it twice (right?), but is there any way (without an intermediate variable) to have it check the condition AND be in the return statement at the same time?
The first implementation will call this.gameOver(gpos) twice. I don't know of a clean way to conditionally return that value without storing in a temporary. Is there some reason that you cannot use a temporary variable here? There are some hackish solutions that make the code less readable (and probably slower).
I believe the observer pattern would work well here.
Essentially, you would have something like a observer Console Class (think xbox console, etc.), which is an observer of any observable Game class. When the game is completed, it could fire an event to notify the Console that the Game is complete, beaten, paused, etc.
Many GUI frameworks like GWT, RCP, etc. can make use of observer to publish events between windows/views.
While I believe this is bad design, I do believe it allows for what you want:
boolean gameOver(GamePosition gp) {
// example
if (this.gameOver)
return true;
else
throw new Exception();
}
void someMethod() {
try {
return gameOver(gp);
} catch (Exception e) {
// other logic for when the game is not over
}
}
Now, a better design would be to just have a method isGameOver(gp), and as you mentioned, store that to a local variable.
In my application I am using a third-party API. It is a non-blocking method which returns immediately. I have a collection of elements over which I have to invoke this method.
Now, my problem is that I have to find a way till all the method execution gets completed and do my next operation. How can I handle this? I cannot modify the third-party API.
In short it looks like this
for(Object object: objects){
methodA(object); //this is a non-blocking call and returns immediately
}
// here I want to do my next task only after all the methodA calls completed execution
What you are asking for is impossible ... unless the third party API also includes some method that allows you to wait until one or more calls to methodA have completed.
Does it?
EDIT
As Kathy Stone notes, another possibility is that the API might have a callback mechanism, whereby a thread (behind the API) that is doing the work started by the methodA call "calls back" to your code. (There would need to be some other method in the API that allows you to register the callback object.)
There are other possibilities as well ... (some too horrible to mention) ... but they all entail the API being designed to support synchronization with end of the tasks started by methodA.
As Stephen noted it is possible if you have some way of knowing that the method has completed. If you have some kind of callback or listener for this you could use something like a counting semaphore:
final Semaphore block = new Semaphore();
//HERE SOMETHING APPROPRIATE TO YOUR API
myAPI.registerListener(new APIListener(){
public void methodADone(){
block.release();
}
});
int permits = 0;
for(Object object: objects){
methodA(object); //this is a non-blocking call and returns immediately
permits++;
}
block.acquire(permits);
Of course you would need extra checking to make sure you are releasing permits for the correct object collections, depending on how your code is threaded and what mechanism the API provides to know the call has completed, but this is one approach that could be used.
How do you dertermine a methodA() call has finished?
Does the method return any handle? Or do the object has any property to be set by the methodA() call? So collect them an do a loop with sleep and check all remaining handles or object properties, each removed from the remaining if completed.
The waiting code cann look like:
while(!remaining.isEmpty()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
continue;
}
Iterator<HandleOrObjectWithProperty> i = remaining.iterator();
while (i.hasNext()) {
HandleOrObjectWithProperty result = i.next();
if (result.handleHasFinishedOrPropertyIsSet()) {
i.remove();
}
}
}