2

I have seen this answer: How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?

But it is not what I am asking since my calling class has multiple calls to the AsyncTask.

I want to create a generic AsyncTask class which will accept the URL and download content from the given URL and return the downloaded content.

Example:

public class MyAsyncTask extends AsyncTask<String, Void, String>{
    ProgressDialog dialog;

    protected void onPreExecute() {
        super.onPreExecute();
        dialog = ProgressDialog.show(context, "Loading", "Please wait...", true);
    }

    protected String doInBackground(String... params) {
        // do download here
    }

    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        dialog.dismiss();
    }
}

And I have another class which calls this AsyncTask in different scenarios

public class MyClass {

    public method1(String url) {
        String result = new MyAsyncTask().execute(url).get();
    }

    public method2(String url) {
        String result = new MyAsyncTask().execute(url).get();
    }
}

I know that using get() method will make this entire process a sync task. But I want to get the result back to calling class. And I also know, to prevent it, I have to implement an interface. But since I have multiple calls in the same class it is not possible. So can anyone give me an idea to solve this?

Community
  • 1
  • 1
Andi
  • 21
  • 1
  • 2

5 Answers5

6

As doInBackground works in background you can not get the result in it's return value while calling from activity.

You need to set a callback which will get called with the result.

For ex:

interface Callback{
void onResult(String result);
}

Make your activity implement this and in activity

void onResult(String result){
    //Do something
}

Now change your asyncTask to:

public class MyAsyncTask extends AsyncTask<String, Void, String>{

   ProgressDialog dialog;
   Callback callback;
public MyAsyncTask(Callback callback){
 this.callback=callback;
}
protected void onPreExecute() {
    super.onPreExecute();
    dialog = ProgressDialog.show(context, "Loading", "Please wait...", true);
}

protected String doInBackground(String... params) {
    //do download here
}

protected void onPostExecute(String result) {
    super.onPostExecute(result);
    callback.onResult(result);
    dialog.dismiss();
}
} 

At the time of starting this task from activity:

 new MyAsyncTask(new Callback{
void onResult(String result){ 
 //Do something
}
}).execute(url);

So when you get a response onResult will get called

vipul mittal
  • 17,343
  • 3
  • 41
  • 44
  • 1
    but my activity has multiple calls to the async task. So my onResult () method will get fired in different occasions. How can I resolve that? – Andi Jul 16 '14 at 06:33
  • one way is to give a different call back for each call to async task. Check my edit. – vipul mittal Jul 16 '14 at 06:36
1

Why would making multiple calls in the same class break an interface?

class Task extends AsyncTask{

    public interface TaskDoneListener{
        public void onDone(String result);
    }

    private TaskDoneListener listener;
    public Task(TaskDoneListener list){
        super();
        listener = list;
    }

    public void onPostExecute(String result){
        listener.onDone(result);
    }
}
kalyan pvs
  • 14,486
  • 4
  • 41
  • 59
Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
0

I suggest you create an abstract class for that:

public abstract class AsyncDownloader extends AsyncTask<...> {
    doInBackground(Params...){
        return doNetworkDownload();
    }
    ABSTRACK onPostExecute(Result);// Notice there's no method body
}

Then in any of your Activities, where Downloading task is the same, but parsing is different, extend this class:

public class MainActivityAsyncTask extends AsyncDownloader {
    //It will give you error, that you must implement the onPostExecute method at first
    @Override
    onPostExecute(Result){
        doUiStuff();
    }
}
Marius
  • 810
  • 7
  • 20
0

In your class override the onPostExecute to get the result back to your class.

MyAsyncTask mytask = new MyAsyncTask(){
    @Override
    protected void onPostExecute(String result) {
        //your code
    }
}
mytask.execute(url);
stealthjong
  • 10,858
  • 13
  • 45
  • 84
null pointer
  • 5,874
  • 4
  • 36
  • 66
0

You should have to make interface and in that interface add one method that has argument type that you want to return from AsyncTask.

and in a constructor of AsyncTask pass interface reference from your activity. and set data in interface method from onPostExecute().

so you will be notifyed in activity class when data set from onPostExecute method.

follow this nice answer https://stackoverflow.com/a/9963705/942224

Community
  • 1
  • 1
Sanket Kachhela
  • 10,861
  • 8
  • 50
  • 75
  • 1
    It's all right although if an operation takes too long, may not be available the result in `onTaskCompleted`, that Problem was already documented but we can overcome it with a customized event. One of implementations of the AsyncTask which overcomes, is `AsyncTaskLoader` and its subclass `Cursorloader`. Be aware of generic implementations of `AsyncTask` i.e. I had to develop an app which populated a ListView with data from a Server and was not populated until I developed my own customized event. – Gödel77 Jul 16 '14 at 06:54
  • @Gödel77 thanx for suggestion.. may i get any brief document link for that? – Sanket Kachhela Jul 16 '14 at 07:33
  • I have no code here, for this case I meant, just develope your own event type with proper Listener. This Listener should listen that the List from Server not empty is (when the list not empty is, we fire our event!), then we can fill our adapter with the list. You know, `CustomAdapter ourAdapter = new CustomAdapter(..., list)` and `listView.setAdapter(ourAdapter)`. – Gödel77 Jul 16 '14 at 16:29