In regards to Async Task in android it is best practice to include them as a Inner Class of the Activity you are working in or is it better to have the as their own stand alone class? for example
public MyClass extents Activity
{
public void onCreate(){
}
public class MyAsyncTask extents AsyncTask<Void, Void, Void>
{
protected void doInBackground()
{
//do stuff here....
}
}
public void onResume(){
}
}
or as an external class
public class MyAsyncTask extents AsyncTask<Void, Void, Void>
{
protected void doInBackground()
{
//do stuff here....
}
}
public MyClass extents Activity
{
public void onCreate(){
}
}
AsyncTask has it's own lifecycle which doesn't depend on Activity lifecycle. You need to make sure that it doesn't have a reference to activity or views when activity is already destroyed.
Implementing AsyncTask as an inner class makes sense only if it's static. If it's not static then it will have an implicit reference to outer activity which will lead to memory leaks. If you need references to views from your static async task use WeakReference.
Implementing AsyncTask in a separate file is also a good idea, but same rules applied. Use weak references if needed.
The only difference between static inner async task and async task in a separate file is code readability. If there is a lot of logic inside async task, go ahead with a separate file.
Related
I have 3 activities A,B,C. In all the 3 activities i'm using Async task. Is it possible to run all the Async task under a single Async task(Common code).
If possible
1. How to check which task called from which activity?
2. How to check whether the task got completed or not?
May be you want to have a Common async task for that can used to perform long running taks and you want a callback machanism to it use this,
You can implement the same by taking async task class a separate abstract and by implementing a callback interface.
Async Class with callback
Yes it is possible.
Add a Parameter that is used to indicate the calling Activity
Look at JavaDoc of AsyncTask method onPostExecute()
Create your AsyncTask class
public class MyTask extends AsyncTask<Void, Void, Void>
{
// Use a WeakReference instead of holding the Activity object
private WeakReference<Activity> mActivity;
public MyTask(Activity activity)
{
mActivity = new WeakReference<Activity>(activity);
}
#Override
protected Void doInBackground(Void... params)
{
// do common work
return null;
}
public Activity getActivity()
{
return mActivity.get();
}
public void setActivity(Activity activity)
{
mActivity = new WeakReference<Activity>(activity);
}
}
And in each Activity:
MyTask t = new MyTask(YourActivity.this)
{
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
// do some work when finished
}
};
I have utility class with static methods. Assuming that these methods can fire background task, something like below:
class ExampleAsyncUtil {
public static void doSomeAsyncJob() {
new AsyncTask<Void, Void, Void> () {
#Override
protected Void doInBackground (Void... params) {
//do heavy job here ...
return null;
}
}.execute();
}
}
if then i call the util class method inside activity which then becomes destroyed:
class ExampleActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ExampleAsyncUtil.doSomeAsyncJob();
}
#Override
protected void onDestroy() {
//should i stop async task in util on destroy ?
super.onDestroy();
}
}
Does it do any harm? (assuming that the background thread does not keep any refrence to activity which called the utility method)
Yes, you should cancel the AsyncTask from your UI. You can leak the AsyncTask otherwise (talking from experience). And, who knows, maybe even block another from being started on the same thread: they keep changing the implementation: http://developer.android.com/reference/android/os/AsyncTask.html. Or, contrary, multiple onCreate() could create duplicate "zombie" AsyncTask's. Anyway, it's not an intended use of AsyncTask: they are supposed to be short-lived and properly controlled. So, there seems to be no real gain in that static business.
I think you should either start a Service and spawn a tread from it or just use AsyncTask traditionally, within the life cycle of your Activity.
There is a good tutorial on asynchronous handling here: http://www.vogella.com/articles/AndroidPerformance/article.html.
I am developing an application in which i need to send the value of the asynctask's onPostExecute method's result in to the previous activity , ie the activity in which the aync task is being called.pls put some codes. Anyhelp is appreciated
Two ways:
Declare class extending AsyncTask as private class in parent Activity
Pass Handler or Activity itself as param of class extending AsyncTask
If I were you, I'd follow the first option.
Look at DOCS:
class MyActivitySubclass extends Activity {
function runOnPostExecute(){
// whatever
}
private class MyTask extends AsyncTask<Void, Void, Void> {
void doInBackground(Void... params){
// do your background stuff
}
void onPostExecute(Void... result){
runOnPostExecute();
}
}
}
Note 1
Code placed in body of function onPostExecute is already run on Activity thread, you should just mention that this keywords leads to MyTask.this and not MyActivitySubclass.this
Well if your AsyncTask is an inner class, you could simply call a method in your activity from onPostExecute():
public class MyActivity extends Activity {
public void someMethod(String someParam) {
// do something with string here
}
public class InnerTask extends AsyncTask<...> {
protected void onPostExecute(result) {
someMethod(Send parameters);
}
}
}
The onPostExecute method is fired on the main UI thread, so anything done there is already on the AsyncTasks caller.
http://developer.android.com/reference/android/os/AsyncTask.html
Fire an event in the OnPostExecute.
Its an add on to the answer by Marek Sebera, he pointed to use a handler. To keep the code simple and intuitive use an interface. This isn't alien concept, we use it all the time for callback functions (eg: OnClickListner etc..). The code would look some thing like this.
public class InnerTask extends AsyncTask<...>
{
interface ResultHandler
{
void gotResult(<> result);
}
private ResultHandler myResult;
//constructor
public InnerTask(....params...,ResultHandler callback)
{
...
this.myResult = callback;
}
protected void onPostExecute(<>result)
{
...
myResult.gotResult(result);
}
}
public class MyActivity extends Activity implements InnerTask.ResultHandler
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
//do something
//if you want the InnerTask to execute here
InnerTask i = new InnerTask(....params...,this); //send 'this' as parameter
i.execute();
}
#Override
public void gotResult(<> result)
{
//from onPostExecute
}
}
If we want to use the same AsynTask class at multiple sites we can use this type of implementation instead of using nested classes implementation.
I am launching a activity, and once a user is logged in, i want to refresh the main activity. To load the data from the logged in user.
Such as the image and name. I have all of this set up already.
I just need to know is it possible to launch another activity and run its async task again.From an launching an intent from inside another activity?
It's not clear what exactly your design is, but if you need to use the same AsyncTask from two different activities, it should be a separate class, not tied to a particular activity. You can have the two activities implement a common interface, so that the AsyncTask doesn't need to know which activity it is updating. Then instantiate the task by passing a reference to the enclosing activity, and start it as needed. There is no need for one activity to start the other.
Something like:
public interface UserActivity {
void updateUserData(UserData userData);
}
public class Activity1 implements UserActivity {
public void onStart() {
UpdateUserDataTask task = new UpdateUserDataTask(this);
task.execute();
}
public void updateUserData(UserData userData) {
// update
}
}
public class UpdateUserDataTask extends AsyncTask<Void, Void, UserData> {
UserActivity userActivity;
public UpdateUserDataTask(UserActivitiy userActivity) {
this.userActivity = userActivity;
}
// doInBackground, etc implementation.
protected void onPostExecute(UserData userData) {
userActivity.updateUserData(userData);
}
}
As far as I'm aware, AsyncTasks aren't supposed to be reused. They're supposed to be run once and then you can create a new one if you need it.
Once an AsyncTask is executed once, you cannot execute it again. What you can do, though, is control it's "refresh" using onProgressUpdate() and publishProgress() as follows. Note that this will only work for a one-time refresh. If you wanted to be more semantically correct, you might do the "normal" operation in onProgressUpdate() and use onPostExecute() for your resfresh.
public class MyAsyncTask extends AsyncTask<Void, String, Void> {
private boolean isRefresh = false;
#Override
protected Void doInBackground(Void... arg0) {
while (!isRefresh){
//Perform your normal operation
}
//When isRefresh is true, you want to refresh.
this.publishProgress(values);
return null;
}
#Override
protected void onProgressUpdate(String... values) {
// Refresh code here
super.onProgressUpdate(values);
}
public void refreshTask(){
this.isRefresh = true;
}
}
You could then maintain a reference to the object of MyAsyncTask and invoke refreshTask() on it whenever you want to refresh it.
I'm currently doing something like this in the AsyncTask's onPostExecute method, where NewTask is not the current task that's executing:
private class OlderTask extends AsyncTask<String, Void, Integer> {
//other functions (not important)
#Override
protected void onPostExecute(Integer result) {
new NewTask().execute(null, null);
}
}
I'm wondering if this is a bad idea. Will doing so cause GC for the OlderTask to wait for the NewTask? Are there any other possible problems with using such an approach?
And if this is a problem, how can I rectify it?
Unless NewTask is inner non static class in OlderTask it will not prevent GC from collecting OlderTask unless you store reference to it in some other way.
But even if GC will wait until NewTask is done it should not be a big deal unless you save lot of data in OlderTask or create lots of copies of OlderTask.
So if your design requires doing that, it's ok. But it surely cleaner not to have chained tasks.
I use a callback method, So when result comes to onPostExecute I call another AsynkTask from UI, I think it is good idea, Let me know what do you think.
public class PatientSearchController extends AsyncTask < String, Void, String > {
private PatientSearchResultHandler handler = null;
public void onResultHandler(PatientSearchResultHandler handler) {
this.handler = handler;
}
#Override
protected String doInBackground(String...params) {
}
#Override
protected void onPostExecute(String result) {
this.handler.onResultSuccessHandler(result);
}
}