The problem in that: I have Observable and Subscriber. I try to launch Observable in .io() thread, because it works with files and zip archivers (I won't show the code - is too large), but Observable do nothing!:
Observable<Double> creatingObservable = getCreatingObservable(image);
Subscriber<Double> creatingSubscriber = getCreatingSubscriber();
creatingObservable
.subscribeOn(Schedulers.io())
.subscribe(creatingSubscriber);
If I launch code without the subscribeOn() - all work. What is the problem and how to solve it
P.S. System.out.println() doesn't work too. Problem have all Scheduler's threads.
It seems the problem is that the main thread terminated before creatingObservable could emit any values.
The simple solution: make the main thread wait long enough to enable creatingObservable to emit/complete.
Observable<Double> creatingObservable = getCreatingObservable(image);
Subscriber<Double> creatingSubscriber = getCreatingSubscriber();
creatingObservable
.subscribeOn(Schedulers.io())
.subscribe(creatingSubscriber);
Thread.sleep(5000); //to wait 5 seconds while creatingObservable is running on IO thread
Try this one:
Subscriber<Double> creatingSubscriber = getCreatingSubscriber();
Observable.defer(new Func0<Observable<Double>>() {
#Override
public Observable<Double> call() {
return getCreatingObservable(image);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(creatingSubscriber);
Don't forget to add:
compile 'io.reactivex:rxandroid:1.2.1'
From here: https://github.com/ReactiveX/RxAndroid
Explanation
getCreatingObservable(image); - most probably you use some operators which do 'hard' work in moment of call.
For example:
Observable.just(doSomeStuff())
.subscribeOn(...)
.observeOn(...)
So, the execution process will be:
1). Calculate doSomeStuff()
2). Pass result to Observable.just()
3). And only passing you are applying schedulers
In other words, you are doing 'hard' work firstly, and then applying schedulers.
That's why you need to use Observable.defer()
For more explanation, please read this article of Dan Lew:
http://blog.danlew.net/2014/10/08/grokking-rxjava-part-4/
Section Old, Slow Code
In this case you app create observable just once. You may try to either use
Observable.defer(()-> creatingObservable) so .defer operator will force observable creation every time.
Observable.defer(new Func0<Observable<Double>>() {
#Override
public Observable<Double> call() {
return getCreatingObservable();
}
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(getCreatingSubscriber);
Related
It's a simplified function.
It keeps returning 0 while I expect this to return 5. How come?
public int accessKey() {
a = 0;
mSubscription = mAccountManager.getLoginPassword()
.flatMap(loginPassword -> mServerAPI
.getProfilesList((new BaseRequest(
loginPassword.getLogin(),
loginPassword.getPassword(),
ClientGetter.getClientFromManager(),
CodeSnippets.getSha256(ClientGetter.getClientFromManager()))
)))
.doOnNext(profilesListe -> mProfilesList = profilesListe.getItems())
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<BaseResponse>() {
#Override
public void onCompleted() {
a =5;
}
return a; }
It's because of the asynchronous or non blocking behaviour , Normally during the scenarios of API calls fetching some data from database ,these behaviours we handle asynchronously,because otherwise your application will get stuck This post will help you to solve this matter. Refer this
you're executing an asynchronous operation here. your code doesn't execute "top down" here but will be executed on a different thread - Rxjava shifts this entire operation over to another thread and then returns the result to the thread specified, but this doesn't happen immediately. by the time your subscribe code has executed (we don't know when that will be) your return statement has already executed.
you could try change your code to something like this (just as an idea, i don't have any code similar to yours to create a working example):
return mAccountManager.getLoginPassword()
.flatMap(loginPassword -> mServerAPI
.getProfilesList((new BaseRequest(
loginPassword.getLogin(),
loginPassword.getPassword(),
ClientGetter.getClientFromManager(),
CodeSnippets.getSha256(ClientGetter.getClientFromManager()))
)))
.doOnNext(profilesListe -> mProfilesList = profilesListe.getItems())
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
this means that your method will now return an observable, which you can then subscribe on and subscribe to those changes where they are used.
this means that the signature of your method will have to change to support this new return type and the calling method will have to subscribe to this observable.
you describe your question as a simplified function, but I'll give you an even simpler (complete) example:
public Observable<Integer> foo() {
return Observable.just(5);
}
public void usage(){
Disposable disposable = foo().subscribeOn(something).observeOn(something).subscribe(
//inside this subscribe, like you'd normally do, you'd find the result of 5
)
...
//handle disposable
}
I used the Callback interface method and it worked! Many thanks
I am using a proprietary, 3rd party framework in my Android app -- EMDK from Zebra, to be specific -- and two of their exposed methods:
.read() and .cancelRead() are asynchronous, each taking anywhere from a split second to a 5 whole seconds to complete. I need to be able to spam them without crashing my application and ensure that each one isn't called twice in a row. How can I go about doing this? I don't have any access to the methods themselves and a decompiler will only give me runtime stubs.
Edit: I also have no idea when each of these two calls ever completes.
Changing asynchronous programs into blocking ones is a more general requirement to this problem.
In Java, we can do this with CountDownLatch (as well as Phaser), or LockSupport + Atomic.
For example, if it is required to change an asynchronous call asyncDoSomethingAwesome(param, callback) into a blocking one, we could write a "wrapper" method like this:
ResultType doSomethingAwesome(ParamType param) {
AtomicReference<ResultType> resultContainer = new AtomicReference<>();
Thread callingThread = Thread.currentThread();
asyncDoSomethingAwesome(param, result -> {
resultContainer.set(result);
LockSupport.unpark(callingThread);
});
ResultType result;
while ((result = resultContainer.get()) == null) {
LockSupport.park();
}
return result;
}
I think this will be enough to solve your problem. However, when we are writing blocking programs, we usually want a "timeout" to keep the system stable even when an underlying interface is not working properly, for example:
ResultType doSomethingAwesome(ParamType param, Duration timeout) throws TimeoutException {
AtomicReference<ResultType> resultContainer = new AtomicReference<>();
Thread callingThread = Thread.currentThread();
asyncDoSomethingAwesome(param, result -> {
resultContainer.set(result);
LockSupport.unpark(callingThread);
});
ResultType result;
long deadline = Instant.now().plus(timeout).toEpochMilli();
while ((result = resultContainer.get()) == null) {
if (System.currentTimeMillis() >= deadline) {
throw new TimeoutException();
}
LockSupport.parkUntil(deadline);
}
return result;
}
Sometimes we need more refined management to the signal among threads, especially when writing concurrency libries. For example, when we need to know whether the blocking thread received the signal from another thread calling LockSupport.unpark, or whether that thread successfully notified the blocking thread, it is usually not easy to implement with Java standard library. Thus I designed another library with more complete mechanism to solve this issue:
https://github.com/wmx16835/experimental_java_common/blob/master/alpha/src/main/java/mingxin/wang/common/concurrent/DisposableBlocker.java
With the support of DisposableBlocker, life will become much easier :)
ResultType doSomethingAwesome(ParamType param, Duration timeout) throws TimeoutException {
// We can use org.apache.commons.lang3.mutable.MutableObject instead of AtomicReference,
// because this object will never be accessed concurrently
MutableObject<ResultType> resultContainer = new MutableObject<>();
DisposableBlocker blocker = new DisposableBlocker();
asyncDoSomethingAwesome(param, result -> {
resultContainer.setValue(result);
blocker.unblock();
});
if (!blocker.blockFor(timeout)) {
throw new TimeoutException();
}
return resultContainer.getValue();
}
Might be off on this as I'm not 100% sure what you're trying to achieve/nor the structure, but could you wrap each in an AsyncTask? Then in a parent AsyncTask or background thread:
AsyncTask1.execute().get(); //get will block until complete
AsyncTask2.execute().get(); //get will block until complete
This is assuming there is some way of knowing the calls you're making completed.
I have a list a want to refresh every minute.
For example the user list here : https://github.com/android10/Android-CleanArchitecture/blob/master/domain/src/main/java/com/fernandocejas/android10/sample/domain/interactor/GetUserList.java
I add a periodical refresh using repeatWhen :
public Observable<List<User>> buildUseCaseObservable(Void unused) {
return this.userRepository
.users()
.repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
#Override
public ObservableSource<?> apply(Observable<Object> objectObservable) throws Exception {
return objectObservable.delay(1, TimeUnit.MINUTES);
}
});
}
It works fine this way, calling onNext every minute.
But if I want to refresh immediately this list (because of user's action or because of a notification), I don't know how to perform that.
Should I cancel/dispose the observable and restart a new one ?
Thanks
From your code I understand that the users list is generated and emitted upon subscription.
Here are some solutions I can think of, instead of unsubscribing and resubscribing upon the event to which you want to react immediately:
Instead of using the repeatWhen operator, use the interval creation operator combined with the flatMap to invoke the subscription to a new Observable every minute and use the merge operator to add reaction to the other event in which you are interested. Something like this:
#Test
public void intervalObservableAndImmediateReaction() throws InterruptedException {
Observable<String> obs = Observable.interval(1, TimeUnit.SECONDS)
.cast(Object.class)
.mergeWith(
Observable.just("mockedUserClick")
.delay(500, TimeUnit.MILLISECONDS))
.flatMap(
timeOrClick -> Observable.just("Generated upon subscription")
);
obs.subscribe(System.out::println);
Thread.currentThread().sleep(3000); //to see the prints before ending the test
}
or adjusted to your needs (but the principal is the same):
Observable.interval(1, TimeUnit.MINUTES)
.mergeWith(RxView.clicks(buttonView))
.flatMap(timeOrClick -> this.userRepository.users());
You can use the flatMap operator as before, even while keeping you working current implementation and without merging to an interval - just keep your working code and in another area of the programme chain it to the RxBinding of your choosing:
RxView.touches(yourViewVariable)
.flatMatp(motionEvent -> this.userRepository.users())
.subscribe(theObserver);
Note that in this solution the subscription is done independently to the two observables. You'll probably be better off if you use different observers, or manage a subject or something on that line. A small test I ran showed one subscriber handled subscribing to 2 different observables with no problem (in Rxjava1 - didn't check in Rxjava2 yet), but it feels iffy to me.
If you aren't concerned with adjusting the refresh time after one of the other observables emits data you can do something like the following:
// Specific example of a user manually requesting
val request = Observable.create<String> { emitter ->
refresh.setOnClickListener {
emitter.onNext("Click Request")
}
}
.observeOn(Schedulers.io())
.flatMap {
userRepository.users()
}
// Refresh based off of your original work, could use something like interval as well
val interval = userRepository.users()
.subscribeOn(Schedulers.io())
.repeatWhen { objectObservable ->
objectObservable.delay(1, TimeUnit.MINUTES)
}
// Combine them so that both emissions are received you can even add on another source
Observable.merge(request,interval)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
contents.text = it.toString()
}, {
contents.text = it.toString()
},{
println(contents.text)
})
Then you don't have to dispose and resubscribe every time
I have a connectable observer with multiple subscribers.
Each subscriber computes some business logic. For example one of subscribers stores results in database on every onNext call, other subscriber accumulates it's results in memory and when onCompleted called writes them to file. I want to know when they all finished their work, so I can proceed in doing other stuff (aggregating with other connectable observers, read outputed data from database etc).
This is how I'm observing termination. It's only working because subscribers execute in the same thread as observer.
public Observable<Boolean> observeTermination() {
return Observable.defer(() -> {
try {
start();
return Observable.just(true);
} catch (RuntimeException e) {
return Observable.just(false);
}
});
}
void start() {
Observable<List<Foo>> fooBatchReaderObservable = fooBatchReader.createObservable(BATCH_SIZE);
ConnectableObservable<List<Foo>> connectableObservable = fooBatchReaderObservable.publish();
subscribers.forEach(s -> connectableObservable.subscribe(s));
connectableObservable.connect();
}
So when observeTermination gets called I don't want to execute logic in start method, but only when someone subscribes to it.
Is there a way to make observation better ?
Well, it's all bad. The problem is that I need to call connect on observable somewhere and also return boolean results as inication of termination.
Not a proper answer, but it needs the space to explain properly. It would be much easier if you could deal with Observables instead of Subscribers; that gives you much more flexibility in composing them;
Given that you have components:
Collection<Function<Observable<T>, Observable<?>>> components:
Observable<T> tObs = ... .publish().autoConnect(components.size());
Observable
.from(components)
.flatMap(component -> component.apply(tObs))
.ignoreElements()
.doOnTerminate() // or .defaultIfEmpty(...), or .switchIfEmpty(...)
.subscribe(...);
In fact, I'd say you should not even subscribe at all here, just create the observable and return it, let it be usable for composition in other parts of your code.
I have this piece of a Java method I'm working on right now:
Observable<Map.Entry<String, ConstituentInfo>> obs = Observable.from(constituents.entrySet());
Subscriber<Map.Entry<String, ConstituentInfo>> sub = new Subscriber<Map.Entry<String, ConstituentInfo>>(){
String securityBySymbol, company, symbol, companyName, marketPlace, countryName, tier, tierId;
ConstituentInfo constituent;
Integer compId;
#Override
public void onNext(Map.Entry<String, ConstituentInfo> entry) {
logger.info("blah blah test");
}
#Override
public void onCompleted() {
logger.info("completed successfully");
}
#Override
public void onError(Throwable throwable) {
logger.error(throwable.getMessage());
throwable.printStackTrace();
}
};
obs.observeOn(Schedulers.io()).subscribe(sub);
The method essentially processes each entry in the Map.Entry, but this seems to be processing it sequentially (same thread). How would I go about making this process asynchronous without using the "parallel" operator (i.e. process entries concurrently)? I tried to run the code above and I am missing some results (some are not processed properly).
Your observable is run on the main thread as it is reported and the Subscriber methods will be called by one worker given by Schedulers.io() so that is why it appears on one thread. Your code does not indicate any real work being done beyond logging by the subscriber so there is nothing to do asynchronously here.
Perhaps you meant to do this?
obs.subscribeOn(Schedulers.io()).subscribe(sub);
In terms of parallel processing if your last line was this:
obs.doOnNext(entry -> doWork(entry)).observeOn(Schedulers.io()).subscribe(sub);
Then you could have the doWork bit done asynchronously like this:
int numProcessors = Runtime.getRuntime().availableProcessors();
obs.buffer(Math.max(1, constituents.size()/numProcessors))
.flatMap(list -> Observable.from(list)
.doOnNext(entry -> doWork(entry)
.subscribeOn(Schedulers.computation())
.observeOn(Schedulers.io())
.subscribe(sub);
You need to buffer up the work by processor otherwise there could be a lot of thread context switching going on.
I'm not sure why you are missing results. If you have a repeatable test case then paste the code here or report it to RxJava on github as an issue.