Unable to get the result of AsyncTask - java

I have a AsyncTask class that is separate from the MainActivity.
protected void onPostExecute(ArrayList<String> result) {
System.out.println("flag1");
MainActivity.myLst=new ArrayList<String>();
MainActivity.myLst=result;
}
then I have the following code in my MainActivity.
public void onCreate(Bundle savedInstanceState) {
new AsyncTask().execute();
System.out.println("flag2");
System.out.println(myLst.size());
}
The program outputs the flag2 first and myLst.size is 0. If I negative to other activity and then come back to the main activity and myList.size has the correct size. I thought It should output everything and do the work in AsyncTask before the MainActivity.

The AsyncTask doesn't "do the work before MainActivity", that would defeat the purpose of an AsyncTask.
What you want to do is write up an interface to pass the value back to your Activity. This answer has a good example of that.

You're creating an AsyncTask to do stuff asynchronously.
You're saying to another thread that it has work to do, but you're not waiting his result to do yours, that's why "flag2" is written before the other.
if you want to wait the result, you need to implement a callback in onPostExecute()

Asynchronous means that it may be out of order. An asynchronous task often launches another thread that does the work in parallel, or in the background, to the main thread. You absolutely cannot assume that the asynchronous task will be completed when execute() returns!

Like other have said and like I have said in the comments to your post, async means asynchronously, and in your case means it will probably finish the onCreate code before finishing the async task.
Either put the AsyncTask class inside your MainActivity (and call some method to print on PostExecute), or implement an Observing/Observer style in your activities to be able to notify your main activity that the async task is over.

You can just overwrite the onPostExecute() method inside the the code that calls the Asynctask.
For example,you have a AsyncTask called myAsyncTask. Then in your Activity do it like this:
new myAsyncTask() {
#Override
protected void onPostExecute( Result result ) {
super.onPostExecute( result );
// Do something with result here
}
}.execute(value1);
I had the same issue, I wanted to get the result inside a fragment....
Look at this topic

Related

Does starting an AsyncTask inside onResume method does cost more memory?

I use AsyncTask to update list from local database(sqlite) as the following :
#Override
public void onResume() {
super.onResume();
new MyAsynctask().execute();
}
I need a clear explanation what happen every time when new MyAsynctask execute and what happen to the previous MyAsynctask that was created earlier, and if this way cost more memory?
Your new async task does nothing.
AsyncTasks are executed after each other.
Only when your old async task ends the new one will start running.
AsyncTask is just a implementation of thread to manage Background task and UI updation . AsyncTask is designed to be a helper class around Thread and Handler in android .From the documentation .
AsyncTask enables proper and easy use of the UI thread. This class allows you to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
So for your question each time you call new MyAsynctask().execute(); A new thread will starts . And the older one will run also if not finished .
To cancel previous task you can use a global instance of task and check if status is RUNNING by getStatus()
if(asyncTask!=null && asyncTask.getStatus()== AsyncTask.Status.RUNNING){
asyncTask.cancel(true);
}
In your case you create new task in onResume() so each time your activity resumes new thread will created and this is not memory efficient solution to refresh screen.
For more detail on cancel task read Section Cancelling a task and cancel(boolean).
If you know how to manage it, then it's not a memory leak.
Your AsyncTask will be executed inside the onResume() function, thus it will run when:
Every-time the Activity is (re)created
You come back from another Activity
You change screen orientantion
You come back from another Application started by an Intent
You close and re-open your App
...
You might want to keep a class field for your AsyncTask and instantiate it in onCreate():
private MyAsyncTask asyncTask;
In case the Activtyis not destroyed (points: 1, 2 (maybe), 4(maybe), 5(maybe)), you can easily check the asyncTask status and cancel it if needed.
The problem is that the old AsyncTask might still be running when you start a new one if the Activity was re-created. And since the Activity instance is new, the asyncTask reference will point to a new Object as well: in that case you will have a savage Thread running in the background.
Unless Android's OS kills Activity's owned Thread (not sure about that), you might still get away by knowing and making sure that your AsyncTask will run for a few seconds at most, without performing any blocking IO operation. But this isn't really an engineered solution.
I'd say, the best and more standard-compliant solution is: by keeping the reference to the AsyncTask in your Activity, just call asyncTask.cancel() in your onPause() method. And you'll be sure that the AsyncTask's thread will be canceled before your Activity is either paused or destroyed.
Your code will then look like this:
private MyAsyncTask asyncTask;
protected void onCreate() {
this.asyncTask = new MyAsyncTask();
}
protected void onResume() {
this.asyncTask.execute();
}
protected void onPause() {
this.asyncTask.cancel();
}

Code in OnCreate isn't being run in order

I am not writing my whole code, I have the following simple structure:
public class CreateEventActivity extends ActionBarActivity{
int x;
void onCreate(){
new AsyncTask1().execute();//here I change the value of x
Log.i("000000",String.valueOf(x));
}
public AsyncTask1 extends AsyncTask<Void, Void ,Void>{
// process include changing the vlaue of x to 4
Log.i("111111",String.valueOf(x));
}
}
in the log: the log with the tag 000000 appears before the log with tag 111111 what's going on?
First I thought the problem was because I am chainging the value of x in onPostExecute so I did so in doInBackground and the problem still the same.
what's going on?
AsyncTask is asynchronous. Quoting the documentation:
This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
The reason that you use an AsyncTask is to do work in a background thread (e.g., download some data), followed by some work on the main application thread (e.g., update the UI based upon that data).
is there anyway to avoid this?
Get rid of the AsyncTask, or learn how to use it properly. Among other things:
Do not modify the same data in multiple threads without appropriate synchronization logic
Do not try to fork a background thread, then block the main application thread (which appears to be what you want), as that eliminates the entire point of the background thread in the first place
If you have work that you want to do when doInBackground() ends, put that work in onPostExecute(), not in statements that follow your execute() or executeOnExecutor() call.
That's the nature of an Async task.
Async Tasks are mostly being used for long running operations; like webcalls, I/O operations and so on as they can take a while.
If you want to have a callback when the AsyncTask finishes you can override the OnPostExecute() method

How do you wait for a thread to finish in Java without freezing the GUI?

I am coding an android game in Eclipse with java. The main goal is to wait for a thread to finish, then to set a boolean to true. The reason is that when a user clicks a button it will only run if the boolean is true. However, when I call a method, it creates a thread and does its thing, then when it is done, it sets the boolean to true. However, it automatically sets the boolean to true while the thread is still running, and so the user can click the button (which messes some things up). Is there a way to wait for a thread to finish without freezing the screen? (thread.join() seems to be freezing it)
Any help is appreciated.
Seems like you don't really need to wait until the thread is done to continue, the way I see it you only need to be notified once it's done, the simplest approach for it would be passing a "callback listener" object to the thread, and execute it when done, this will let you know that you are ready to continue, OR a better approacch would be an AsyncTask which will allow you to do everything in background and when done you can use the onPostExecute method, hope this helps.
This is the way you create and add a callback to be notified when your thread has completed:
//Create your callback listener interface...
public interface MyThreadListener{
public void threadFinished();
}
//This is the method that runs some functionality in a separate thread
public void executeTaskInSeparateThread(final MyThreadListener listener){
new Thread(new Runnable() {
#Override
public void run() {
// DO your long task here...
//Notify when done before leaving run method...
listener.threadFinished();
}
}).start();
}
//Use it like this
//Create the implementation of the listener you want (this is something like what you usually do for buttons or any other android listener)
MyThreadListener listener = new MyThreadListener() {
#Override
public void threadFinished() {
//Do whatever you want when notified...
//NOTE: This method will be called on a separated thread too, you cannot modify views...
}
};
executeTaskInSeparateThread(listener);
Once the thread completed it will execute the listener and will let you know is done...
Regards!
Q: Why not set the button to "disabled" when you start the thread (btn=.setEnabled(false);), then have the thread set the button to "enabled" just before it exits?
And yes, calling "thread.join()" (or ANY blocking call) from your UI thread will indeed "freeze" it :)
PS:
Are you using a Java thread, or an Android "Asynch Task"? Here's an excellent tutorial on the latter:
http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html
Use an AsyncTask. In onPreExecute() disable your button so the user cannot click it again.
In onPostExecute method enable the button again. Do the time consuming logic in the doInBackground method.
try to create a Task extends AsyncTask, override the doinBackground mothed,Then put "time-consuming operation" in it. When your task done,it'll goto "onPostExecute",just use an Interface call back to the Actiity and enable the Button . When you use the AsyncTask you should know that: The Default AsyncTask has got a "pool",System allow 5 instace of AsyncTask ,if you got more than 5 Task,you should create a no limit pool.
My English is so so bad,lol.

After ASyncTask.execute() do x() from Activity

This is one I'm not sure how to go about.
Basically I have an ASyncTask class thats doing its business as usual in the background. I'd like to do something after its finished. Now before you jump ahead and say "just use onPostExecute()", theres a catch. The method I need run is in the activity and not the Task class.
The way I see it, I have 2 options.
A:
CustomTask task = new CustomTask();
task.execute(passedParams);
//when(task.execute is finished)
{
doX();
}
I hope I can do it this way as Its so simple and lets me check when the task is completed without having to constantly poll it for activity and getStatus() on the activity.
I don't think I'll get this lucky but If anyone has a way of doing it, that'd be great
B:
Pass the activity as a paramater to the ASyncTask. This is messy and I'm not happy about using it but asides from that and the object reference, I don't know if it will work
CustomTask task = new CustomTask();
task.execute(passedParams,MyActivity);
Then in the Tasks onPostExecute, I can just have it call the MyActivity.doX();
C:
A third way would be to make the asynctask a private class in the activity itself but i really would like to keep it separate. Resusability and what not –
Any thoughts on this?
To summarize, Need to doX() after task.execute is finished. Any ideas appreciated.
D:
Ok I know I'm on a roll here. I keep thinking up new solutions. A class method or static method that can be called from any where.
public class ProfileSettings extends Activity
{
public static void doX()
{
//Logic...
}
}
From AsyncTask
MyActivity.doX();
Option B should work and is sometimes a good option, but sometimes I use anonymous classes for this. When you call it from your activity:
CustomTask task = new CustomTask() {
#Override
protected void onPostExecute(Long result) {
super.onPostExecute(result);
MyActivity.this.doX();
}
}.execute();
Option A:
Android API has already provided built-in function for this purpose AsyncTask.get():
CustomTask task = new CustomTask();
task.execute(passedParams);
Result result = task.get(); // <- Block UI thread and waiting for AsyncTask finish.
this.doX(result);
As you can see, this is a bad practice as it blocks UI thread and may cause ANR exception, By doing this, you are actually sacrifice the benefit of AsyncTask, and make it running synchronously with UI thread.
Option B and C:
Both are correct way of doing things, by calling doX() method in onPostExecute() method,
AsyncTask, as its name stated, run a background thread asynchronously with UI thread, and once the background thread is finished, onPostExecute method is called on UI thread. There is no way to tell exactly when onPostExecute method is called (i.e. when doInBackground method is finished) at project build time, as it is determined at app run time, the only thing we know is onPostExecute method is guaranteed to be called on UI thread at some point in the future, In another word, when writing code at project build time, we never know exactly when the doInBackground is finished and code execution jump back to UI thread outside onPostExecute method (Unless you implement some waiting mechanism in code like Option A). So the purpose of onPostExecute method is for processing everything after doInBackground method is finish, this is also why the only argument of onPostExecute method is the result returned from doInBackground method.
The difference between Option B and C is whether to implement AsyncTask as inner class or separate class. This has been aksed and discussed many times in StackOverflow. Most people think it is good to separate them for resusability reason or etc. From my point of view, I don't agree with it. Java Programming Language has its reason provide inner class syntax to suit some special coding situations, when talking about code refactoring from a OOP perspective, think more from problem abstraction level, not simply strip inner class out from Activity class at code level. As you can see in your example, by isolating AsyncTask from Activity, you don't gain any real benefit but rather increase the code complexity (need pass activity context reference between classes) to solve problem.
I think you real question is whether or not we should isolate AsyncTask inner class implementation from Activity. For a better OOP code refactoring (reusability, testability and etc.), checkout my answer in this StackOverflow question to see how to isolate business layer from application UI layer properly.
I was able to implement this feature with an interface:
http://howcanisolve.com/38646/android-java-equivalent-of-ios-block-callbacks
public interface ICallbacks {
public void onResponse(JSONObject response);
public void onError(VolleyError error);
}
Then in your routine code just put a new instance of Callbacks:
public static void getPassagesForFirebaseUser(FirebaseUser user,
Context context, ICallbacks events) {
//here code and call ICallbacks methods
if(result){ events.onResponse(response); }
if(error){ events.onError(err); }
}
ultimately you can call the method with :
getPassagesForFirebaseUser(user, context, new ICallbacks(){
#Override
public void onResponse(JSONObject response){
//Success !!!
}
#Override
public void onError(VolleyError response){
//Error !!!
}
});
Option B is generally safer. But even then, you need to be careful. You need to store the instance of your Activity (not just the class) in the ASyncTask. And if the Activity gets destroyed while the task is running (what if the user presses the Back button?), you need to inform the task of this so the task doesn't try to call a method on a dead Activity.
And if the Activity comes back to life (after a screen rotation, for example) then you need to reattach the new Activity to the running task.
These things are fiddly.

Android - Ending activity from within rendering thread

Good afternoon.
I am unfamiliar with the activity life cycle in android and have been reading up as best as possible but I cannot figure how to solve the following in a nice manner.
I have an activity with a GLSurfaceView to draw various things on the screen. In the renderering thread for this GLSurfaceView I perform all the rendering as well as the actual update logic (I will seperate this out eventually).
The trouble I am having is from one of the "screens" drawn within the renderer I wish to end the Activity and have it call the various lifecycle methods.
Normally I might do this with System.exit(0); however ending the activity in this way does not seem to call the OnStop(); OnDestroy(); methods.
This might just be me being silly and not seeing an easy way of doing this but is there a way to access the Activity and call activity.finish(); without having to pass the reference to it all the way down?
This is probably less of an android question and more a general java problem? Sorry I am a little rusty at both. Maybe if someone could explain roughly how they handle an issue like this in their app.
You do need to obey thread safety rules and not call activity.finish() directly from your render thread. The best way to handle this is to post a runnable back onto the event queue for the UI Thread. And let that Runnable call activity.finish().
You don't have to pass the activity down to the area where you plan on stopping the activity. Here is what I'd do. Pass the activity to the class you instantiate in onCreate(). Something like:
public void onCreate( ... ) {
MyRenderer renderer = new MyRenderer( glSurface, this );
}
Then inside MyRenderer I'd do something like:
public void someMethodInRenderer() {
if( stop ) {
stop();
}
}
public void stop() {
Handler handler = new Handler();
handler.post( new Runnable() {
public void run() {
activity.finish();
}
} );
}
Notice the Handler used to post back to the UI thread. That makes it safe to call activity.finish(). I couldn't find any specific information in the docs stating it's safe or not safe to call finish() from another thread so to be on the safe side post it back.
Things to keep in mind. If someMethodInRenderer() is deep within the bowels in your program then you don't have to have access directly to the activity instance. You just need a reference so something that eventually calls to the activity to finish. So maybe there is a reference to another part of the system you are passing down to that method where you can add the stop(). So stop() and someMethodInRenderer() could be in the same class, or in different classes. That's a choice you'll have to make. Eventually this is an architecture issue you have to decide.
If the renderer thread is inside the Activity, you can use ActivityClassName.this.finish();
To address an issue I ran into:
If you finish your activity (including from another thread) via activity.finish() it is important that the render thread's onDraw() method is not blocked (happened to me due to my implementation of double buffer rendering).
In that case, only the onPause() method in the activity class got called. The methods onStop() and onDestroy() weren't called even though the app finished with a short delay.
Hope this helps anybody facing the same problem.
Edit: The reason was, that in my activity.onPause() method I called glSurfaceView.onPause() while the render thread's onDraw() was blocked.

Categories