15

I have a conceptual problem related to AsyncTask class. We use AsyncTask so that the main UI is not blocked. But suppose, I want to retrieve some data from the device's memory, and I use AsyncTask class for this. The relevant line of the code will be as follows (assuming the data type returned is String):

  //code
    String data = new ExtendedAsyncTask().execute(param1, param2).get();
  //use this returned value.

Won't the above line block the UI, defeating the purpose of using the AsyncTask ? If yes, then how do I get the relevant data without blocking UI ? I would like to add that the next line of code will need this data to perform some task, and hence depends on the returned value.

Thanks

Rajat
  • 1,449
  • 5
  • 20
  • 33
  • AsyncTask explained by google : https://developer.android.com/guide/components/processes-and-threads.html#AsyncTask – luc.chante Mar 26 '13 at 11:09

3 Answers3

20

get() method will block the UI thread. To get the relavent data you need to return the value from doInBackground and capture the value in onPostExecute parameter.

Value returned by doInBackground is captured by onPostExecute method

Example:

public class BackgroundTask extends AsyncTask<String, Integer, String >{
       private ProgressDialog mProgressDialog;
       int progress;
       public BackgroundTask() {
           mProgressDialog = new ProgressDialog(context);
             mProgressDialog.setMax(100);
             mProgressDialog.setProgress(0);
    }

       @Override
    protected void onPreExecute() {
           mProgressDialog =ProgressDialog.show(context, "", "Loading...",true,false);
        super.onPreExecute();
    }
     @Override
     protected void onProgressUpdate(Integer... values) {
     setProgress(values[0]);
  }

    @Override
    protected String doInBackground(String... params) {
            String data=getDatafromMemoryCard();    

        return data;  // return data you want to use here
    }
    @Override
    protected void onPostExecute(String  result) {  // result is data returned by doInBackground
        Toast.makeText(context, result, Toast.LENGTH_LONG).show();
        mProgressDialog.dismiss();
        super.onPostExecute(result);
    }
   }

If you are using asynctask in separate class, then use AsyncTask with callback interface like this

Here is the answer I have provided earlier about the same AsyncTask with Callback

Community
  • 1
  • 1
Pragnani
  • 20,075
  • 6
  • 49
  • 74
  • I don't want to display that data, I want to use that data. I got similar results like your's when I googled my problem. – Rajat Mar 26 '13 at 11:12
  • @addresseerajat Read answer completely.. Last two lines discuss about AsyncTask with callback, go to the link once – Pragnani Mar 26 '13 at 11:13
  • Ok, I got some vague idea, but I want this data to be passed to the main UI thread. – Rajat Mar 26 '13 at 11:21
  • @addresseerajat Callback will return data to your UI Thread. Just use the same code. – Pragnani Mar 26 '13 at 11:23
  • Also check this http://stackoverflow.com/questions/9273989/how-do-i-retrieve-the-data-from-asynctasks-doinbackground/14129332#14129332 to get more info @lapslaz due credit to him – Pragnani Mar 26 '13 at 11:25
  • Question: on the ProgressDialog what is the context argument? – Alioo Aug 29 '13 at 21:45
  • 1
    @Alioo If you include this class as an inner class then you can get the context from the parent class in onCreate. Second if you include it as a separate class use single argument Constructor for the bg task. And get context from that argument – Pragnani Aug 30 '13 at 08:34
1

When an asynchronous task is executed, the task goes through 4 steps:

1.onPreExecute(), invoked on the UI thread before the task is executed. use this to diaply progress dialog.

2.doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. Can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.

3.onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). Used to publish progress.

4.onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.

In your activity onCreate()

    TextView tv;
   @Override
   protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);  
    setContentView(R.layout.activity_main);
    tv= (TextView)findViewById(R.id.textView);
    new TheTask().execute();
      
  }
class TheTask extends AsyncTask<Void, Void,String> {

  protected void onPreExecute() {
  //dispaly progress dialog
 }

 protected String doInBackground(Void... params) {
   //do network operation
     return "hello"; 
 }

 protected void onPostExecute(String result) {  
  //dismiss dialog. //set hello to textview
      //use the returned value here.
     tv.setText(result.toString());
 }
 }

Make asynchronous calls, Notifies on the ui thread.

Update: AsyncTask is deprecated. Switch to kotlin coroutines. https://developer.android.com/kotlin/coroutines

Raghunandan
  • 132,755
  • 26
  • 225
  • 256
0

You don't get the result this way. See this link for an example : https://github.com/levinotik/ReusableAsyncTask/tree/master/src/com/example

Basically, here is what you need to do :

  • Define an interface (= a listener) that your activity implements
  • Set the listener in the asynctask
  • Call yourListener.yourMethod() in the onPostExecute
Quanturium
  • 5,698
  • 2
  • 30
  • 36