Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Async tasks reuse

I am developing an app where in a number of the activities I need to retrieve data via Http. Once I have the data I process it in the onPostExecute() callback method.

This works fine if I define the async task as an inline class, but as I want to do the same processing in a number of activities I have defined it as an external class.

So the question is, using an external class how do I signal an "event" back to the calling class as a means of passing the data back. I know how to do this in C# but I am new to Java and can not see how to achieve this.

like image 529
BENBUN Coder Avatar asked Jan 21 '13 21:01

BENBUN Coder


2 Answers

While it is true that a Listener technically correct, I would claim that it is either too complicated or not complicated enough.

Here's an easier solution:

class Foo {
   class Bar extends AsyncTask<Void, Void, Result> {

      public void onPostExecute(Result res) {
         doSomething(res);
      }
   }

   public void doSomething(Result res) {
      /// process result
   }

   public void startTask() {
       new Bar().execute();
   }
}

Is equivalent to:

class Bar extends AsyncTask<Void, Void, Result> {
     private final Foo foo;
     public Bar(Foo foo) { this.foo = foo; }

     public void onPostExecute(Result res) {
       foo.doSomething(res);
     }
}


class Foo {
   public void doSomething(Result res) {
      /// process result
   }

   public void startTask() {
       new Bar(this).execute();
   }
}

... which is what you asked: when you pull the inner class out, you lose the implicit pointer. Just make it explicit and pass it in.

The bad news is that there are all sorts of memory leak and lifecycle issues that arise from this solution. I would very much recommend that, before your program gets even bigger, you looking into using an IntentService instead of an AsyncTask and use a Handler, or Activity.runOnUiThread to get the results back onto the UI thread.

like image 180
G. Blake Meike Avatar answered Sep 28 '22 09:09

G. Blake Meike


One approach:

Define a parent abstract class called ParentActivity (extend Activity of course). Have that contain an abstract method called onAsyncCallback();

Have each class that uses the task to extend that class and implement the method.

In your AsyncTask constructor, have it accept in a ParentActivity.

Eg

ParentActivity activity;
public MyTask (ParentActivity myActivity)
{
 this.activity = myActivity;
}

When done in onPostExecute(), simply do

activity.onAsyncCallback(data);

This would also work with an interface, it does the same thing, except intead you have the Constructor accept in the Listener instance.

like image 39
A--C Avatar answered Sep 28 '22 10:09

A--C