My english is not the best, so I apologize in advance for that.
My situation is the following, I am developing an Android app and I have an async task, and in the doInBackground method have the following code:
#Override
protected Boolean doInBackground(String... params) {
getFirebaseUserChannels(new ResultListener<List<Channel>>() {
#Override
public void finish(List<Channel> firebaseUserChannels) {
if (firebaseUserChannels.isEmpty()) {
getFirebaseChannels(new ResultListener<List<Canal>>() {
#Override
public void finish(List<Channel> firebaseChannels) {
saveChannelsSQLDatabase(firebaseChannels);
saveChannelsFirebaseDatabase(firebaseChannels);
}
});
} else {
saveChannelsSQLDatabase(canalesUsuarioFB);
}
}
});
return true;
}
So, the method "getFirebaseUserChannels" is an async method that in response throws a list, and when that list is ready to use it, I have to evaluate it and use it.
But as you know, java executes the async method and continues until the return.
I want that the "doInBackground" does not continue the execution until all the async methods executions ends.
So, How Could I do that? How is the best way to manage this situation?
How is the best way to manage this situation?
Get rid of the AsyncTask entirely. Have whatever code was going to execute the AsyncTask simply call getFirebaseUserChannels().
Related
I have a plugin method that acts on remote hardware via Bluetooth.
It sends a command to the hardware, which executes some action.
After the hardware action finishes a callback defined outside of my method is called.
I only want to call CallbackContext.success(...) or CallbackContext.error(...) after the callback is called, so i want to wait for my callback to be called.
How would i go about this?
E.g. part of CordovaPlugin-class:
public void actOnHardware(CallbackContext callbackContext)
{
this.verifiyBluetoothEnabled();
this.hardwareConnection.doSomething()
// Now wait for the callback to complete before calling
// callbackContext.success() or error()
callbackContext.error("Not implemented.");
}
#Override
public void hardwareActionCallback(result)
{
// Notify actOnHardware() that we're finished.
}
This seems to be more of a Java thing, but i can't get my head to wrap around it.
Is using Object.wait() and Object.notify() a viable option or does calling wait() prevent the callback from getting called due to thread stuff? If so - how to solve this?
E.g. is it sufficient to just do:
private Object lockObj;
private boolean actionFinished;
public void actOnHardware(CallbackContext callbackContext)
{
this.verifiyBluetoothEnabled();
this.actionFinished = false;
this.hardwareConnection.doSomething()
while(!this.actionFinished)
this.lockObj.wait();
callbackContext.error("Not implemented.");
}
#Override
public void hardwareActionCallback(result)
{
this.actionFinished = true;
this.lockObj.notify();
}
Kind Regards
I have an HTTP request that triggers a long-running task (multiple HTTP requests to another service) that is supposed to be completed in the background while the original requests complete.
So what I do is
public void triggerWork(#RequestBody SomeObject somObject) {
return new ResponseEntity<>(startWorkAndReturn(somObject), HttpStatus.OK);
}
public void startWorkAndReturn(SomeObject someObject) {
Observable.create(observableEmitter -> {
// do the work with someObject here and at some time call
observableEmitter.onNext("result");
}).subscribe(new Observer<Object>() {
#Override
public void onSubscribe(Disposable disposable) {
}
#Override
public void onNext(Object o) {
// called at some unknown time
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onComplete() {
// currently not used as all the work is done in onNext but maybe that's a mistake
}
});
return;
}
But this seems to block the request until all the work has been done. Which already seems odd to me, since I never call onComplete, which in itself might be a mistake. But still, I am wondering how to create a request that immediately returns after triggering a background worker.
Is Flowables the solution here? I am going to refactor to those anyways to handle backpressure. Or do I need to create a background worker Thread? What is the best practice here?
Thanks
I would use Observable.fromCallable{} since you need emit only single event. That will handle onCompleate call. From information you share I don`t know how can you properly handle disposable. You should add subscribeOn() and observeOn() operators that will define on which thread 'work' should be processed and result should be observed.
Docs ref:
http://reactivex.io/RxJava/javadoc/io/reactivex/Observable.html#fromCallable-java.util.concurrent.Callable-
http://reactivex.io/documentation/operators/subscribeon.html
http://reactivex.io/documentation/operators/observeon.html
I need to save the response variable from a request, areaRequest is a RequestContext this works but i can't save it and use it out of the scope
Long temp;
areaRequest.countByCurrentInstitution().fire(new Receiver<Long>() {
#Override
public void onSuccess(Long response) {
temp = response;
}
});
You can't use outside non-final variables inside the Receiver.
A quick and dirty change just to avoid the scope problem would be:
final Long[] temp = {-1};
areaRequest.countByCurrentInstitution().fire(new Receiver<Long>() {
#Override
public void onSuccess(Long response) {
temp[0] = response;
}
});
doSomethingWith(temp[0]);
But that is usually NOT what you want to do. Because (if) countByCurrentInstitution() is an asynchronous call, temp[0] would still be -1 by the time you invoke doSomethingWith(), since the async method is still running in another thread.
You can make your main thread wait a bit by using a simple Thread.sleep() or (yikes!) a very long loop but, again, that's just a quick hack and prone to errors (what if the call takes longer than that?).
The best option is to ditch Long temp and just move your code inside the onSuccess() method:
areaRequest.countByCurrentInstitution().fire(new Receiver<Long>() {
#Override
public void onSuccess(Long response) {
doSomethingWith(response);
}
});
Well, after work a lot of time with GWT the solution that I found to this was create nested async calls.
areaRequest.countByCurrentInstitution().fire(new Receiver<Long>() {
#Override
public void onSuccess(Long response) {
// Here I pass the value from the first request
anotherRequest.anotherFunction(response).fire(new Receiver<Long>(){
#Override
public void onSuccess(Long new_response){ // Long again it could be anything it depends of your function
doWhateverYouWant(new_response)
}
});
}
});
I know there are probably a couple ways to do this, just looking for the most efficient and concise way to go about it:
public Object giveMeNewObject() {
final Object result = null;
SomeApiClient.start(new Callback() { // starts an async process
#Override
public void onSuccess(Object somethingNew) {
result = somethingNew; //ERROR; can't set cause final
}
});
return result; //result is null, cause Async already finished
}
From your code - this is modified on fly so correct mistakes and all will work as you expect - caller will wait untill 3rd party finishes the processing and will get the result of that process:
public Object giveMeNewObject() {
CountDownLatch latch=new CountDownLatch(1);
Callback callback=new Callback() {
public sometype result=null;
#Override
public void onSuccess(Object somethingNew) {
result = somethingNew; //ERROR; can't set cause final
latch.countDown();
}
});
SomeApiClient.start(callback);
latch.await(sometimetowait);
return callback.result;
}
Read the documentation of AsyncTask. Your job should be done in doInBackground method and the result should be returned by that method. Later on you can use get(Timeout) method to retrieve that returned value. get will even block if the computation in doInBackground is not complete yet for given ammount of the time.
You can find tons of examples of how to use async task. One of them is in the API documentation (link above)
I have been searching for the answer but no one really answers because there is no point using async task for that. In Android API 11 or above it will force to code it you do network requests on the main thread so I have to do async task. So, here is the question: Is it possible to wait untill the async task is finished then continue? Because I need the data to be there for the calling method etc.
Here is my code:
public JSONObject getJSONFromUrl(String url) {
this.url = url;
new loadURL().execute();
// Do this when ASYNC HAS FINISHED
return jObj;
}
class loadURL extends AsyncTask <Void, Void, Void> {
protected void onPreExecute() {
}
protected Void doInBackground(Void... unused) {
//do stuff in background
return (null);
}
}
}
Any questions to answer just leave a comment. Thanks for helping.
yes you use the onPostExecute method of the AsyncTask to do whatever you want to do after. That method gets called after the doInBackground is finished
If the operation won't take long (less than a few seconds) you can use the progress bar to keep from allowing the user to do anything. Set something like this in your AsyncTask
ProgressDialog progress = ProgressDialog.show(LoginScreen.this, "Downloading Users", "Please wait while users are downloaded");
#Override
protected void onPreExecute()
{
progress.setCancelable(false);
progress.isIndeterminate();
progress.show();
}
You will still want to call your method from onPostExecute() as this will just keep the user from being able to do anything but it won't keep any code from running that is in the method you calling the AsyncTask from
This can be done with wait(), notify() and notifyAll() methods of objects. Or You can use custom callbacks via interfaces. Just call proper method via callback when you complete getting required data.
You can perform Network related operation inside doInBackground() method because onPostExecute() method is used only for UI updation only in android