I'm wondering where I should place my AsyncTask in my android project. As of right now I'm implementing an AsyncTask as a private class of my activity its running under. What I am going to do is in each activity that has a network call I will implement its own private class of AsyncTask. I have a few questions though
In The preexecute method it says I can interact with the activity and place a spinner or progress bar. I do this by using My_Activity_Class_Name.this. So my question is does that line of code reference the activity the AsyncTask is called from? If so I believe that will be a static method. How do i actually pass in the instance of the class so I can interact with non static functions?
I want to place all my Async code into one class for its respective needs. My quesiotn though is if i need to return a type back to the class that calls the Async method how can I return a value? Also is this the best practice?
You should make your inner private AsyncTask class - static. This is because otherwise it will have implicit reference to your Activity - this means that if your Activity will be recreated - ie. due to config change - then your AsyncTask will still hold your activity reference causing reference leak. This means you should pass reference to your activity to AsyncTask in ie. constructor of AsyncTask, and keep it in WeakReference (WeakReference/AsyncTask pattern in android).
So my question is does that line of code reference the activity the ASYNC Task is called from?
yes, but only if your AsyncTask class is non static
If so I beleve that will be a static method. How do i actually pass in the instance of the class so i can interact with non static functions?
its not a static method, with My_Activity_Class_Name.this you can access non static methods of your Activity class.
My quesiotn though is if i need to return a type back to the class that calls the Async method how can I return a value? Also is this the best practice?
You can call a method on your Activity class, there is nothing wrong with that. Remember that you cannot access UI widgets from non UI thread. So update your Activity widgets from onPostExecute which is called on UI thread.
Related
I am new to Android Development and have a question (will probably show my newbie status). I am calling an asynchtask from a custom activity. Once the asynch task is completed onPostExecute I would like to call back into my activity and set a pojo (Map()). I know that onPostExecute seems to run on the UI thread but I am not sure how to get visibility into the calling Activity.
The goal is to be able to have some variables set in my activity and ideally the webservice call will already be completed.
Thanks,
Craig
If the AsyncTask is a subclass of the activity, it has access to all public, protected, and private variables of the superclass. If its not, you need to write a public function in the Activity class to set the variables, and call it from the AsyncTask. That will probably require you to pass the activity to the AsyncTask via the constructor and save it in a member variable of the task.
I have a class (like a helper class) -not an activity- which manages soap requests. I use this class to send soap requests that comes from activities by method doInBAckground and catch all return values from webservice by onpostexecute. Everything is ok but my problem starts at this point because I could not pass return value asynctask class to main class.
You can have some utility class available as singleton (ok, singleton is dangerous pattern
but it use is justified in android until we get sane and usabel dependency injection ) and pass result there.
Advandatges:
- no messing with intents / serialisability
- pass data or call some methid or do whatever you like
- all your activities share the same instance of singleton service.
Disadvantages:
- singleton pattern is considered dangerous
You may even go further and make your service singleton - you will start methods of it as async tasks, and then your activity may query results over dedicated methods.
Or you may go a step further - register your activity as listener in async service, and call method in this activity when ready (note: as this will be not a UI thread, you will be unable to do something with UI unless you use runOnUiThread()
Have you tried implementing the AsyncTask as an inner class of your Activity?
I wonder which approach is better/cleaner:
Should I pass Context on the constructor and have onPostExecute access the UI thread?
or
Extend my Task class in the UI thread and override onPostExecute (no need to pass Context)?
Passing Context into AsyncTask feels 'dirty' but I don't know whether it's ok 'polluting' the UI class.
I usually use inner classes for this and see no reason why this should be a bad solution, assuming the class implementation is specific to the class into which it's nested.
If you are not going to extend your class in future with another class, then extend it. But I'd rather choose passing the context in the constructor.
I am new to android development. I would like to accomplish a task described as follows:
A main activty which calls external class(the other class would extend AsyncTask) to parse xml and receive json by requesting to web service and starts a ProgressDialog.
The class performs xml and json parsing in its doInBackground method.
In the onPostExecute method after parsing is complete, dismiss the ProgressDialog that was set in the main activity.
I could do this by passing the ProgressDialog object to the parsing class and dismissing the same object in its onPostExecute method.
I think passing an instance of UI object as argument is not a good approach to program, I hope there must be some other ways to work around.
Please suggest.
Thank you
The easiest way to decouple these is to use an interface:
Define a call-back interface (let's call it WorkDoneListener) with a single method: workDone().
Declare your activity class to implement WorkDoneListener and implement workDone() to dismiss the dialog.
Define the AsyncTask's constructor to accept a WorkDoneListener. Stash the reference in a member field.
In onPostExecute, call the listener's workDone() method.
Ted's answer is what you should do if your AsyncTask is too big and you want to declare it in other file. However, keep in mind that usually you declare the AsyncTask inside your UI class:
public class YourActivity extends Activity{
private class YourAsyncTask extends AsynkTask<etc.>{
}
}
In fact, if you are using you AsyncTask from that activity only (I mean, if you are not using it anywhere else), declaring the AsyncTask as a inner class is a good design practice.
This function runs on the UiThread, but it seems that doesnt mean it also has access to the activity context. Shall I implement to my AsyncTask a public Setter to pass the activity (as reference)?
protected void onPostExecute( Bitmap bitmap ) {
//following is underlined red due to missing context
(ImageView)findViewById(ResId)).setImageBitmap(bitmap);
}
I can think about two options.
If the AsyncTask is an inner class of you activity you can use getApplicationContext() to get the Context object, without passing the activity object.
If you have to access the ImageView object from different methods or if the task handled by the AsyncTask class can run multiple times you might think about storing the ImageView object as a member of your activity class, so you can don't need a context to access it.