Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating UI Thread from AsyncTask in public class

I'm trying to split off some AsyncTask classes into public (separate) functions so that I'm not having to rewrite so much code. I almost have it, except for one very important aspect. The AsyncTask function compiles an ArrayList by making php calls to a server. When this list is complete, I need to update a spinner on the main UI thread. I found a really nice answer here but I'm having a little difficulty making it work.

Here is a scaled down version of what I have: (note that at this point, all I am trying to do is to call a Toast message to prove that the round trip is working)

Here is the calling Activity:

public class MyActivity extends Activity implements OnTaskCompleted {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sg_list = new ArrayList<String>();
        new GetSuperGroups(UpdateAffiliationsPreferences.this, context, "Retrieving Group List...").execute();
    }

    public void onTaskCompleted(ArrayList<String> list) {
        Toast.makeText(getApplicationContext(), "hello from async", Toast.LENGTH_SHORT).show();
    }

}

This is the interface:

public interface OnTaskCompleted {
    void onTaskCompleted(ArrayList<String> list);
}

And finally, here is the AsyncTask. Note that it is a Public class:

public class GetSuperGroups extends AsyncTask<String, String, ArrayList<String>> {

    private Activity activity;
    private Context context;
    private String progressMsg;
    private ProgressDialog pDialog;
    private ArrayList<String> sg_list;
    private OnTaskCompleted listener;

    public GetSuperGroups(Activity activity, Context context, String progressMsg) {
        this.activity = activity;
        this.context = context;
        this.progressMsg = progressMsg;
    }

    public void setSuperGroupList (OnTaskCompleted listener){
        this.listener = listener;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(context);
        pDialog.setMessage(progressMsg);
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    @Override
    protected ArrayList<String> doInBackground(String... args) {

        sg_list = new ArrayList<String>();
        //make a php call, compile the ArrayList    
        return sg_list;
    }

    protected void onPostExecute(ArrayList<String> sg_list) {
        pDialog.dismiss();
        //this next line causes a null pointer error
        //note that I am throwing away the array list for now
        //all I want to do is prove that I can call the Toast back in the calling Activity
        listener.onTaskCompleted(new ArrayList<String>());
    }
}
like image 341
AndroidDev Avatar asked Aug 28 '13 04:08

AndroidDev


People also ask

Can we update UI from thread?

Worker threads However, note that you cannot update the UI from any thread other than the UI thread or the "main" thread.

What is the replacement of AsyncTask?

Alternative 1: Using Executor and Handler The executor will help in performing any task in the background and the handler will help to make UI changes.

How can we overcome the AsyncTask limitations?

There are two simple solutions that cover most situations: Either check AsyncTask. isCancelled() on a regular basis during your long-running operation, or keep your Thread interruptible. Either way, when you call AsyncTask. cancel() these methods should prevent your operation from running longer than necessary.

Why did AsyncTask get deprecated?

This class was deprecated in API level 30. AsyncTask was intended to enable proper and easy use of the UI thread. However, the most common use case was for integrating into UI, and that would cause Context leaks, missed callbacks, or crashes on configuration changes.


2 Answers

Just add OnTaskCompleted listener parameter in your asyncTask constructor GetSuperGroups. Then pass this when you execute your asyncTask.

public class MyActivity extends Activity implements OnTaskCompleted {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            sg_list = new ArrayList<String>();
            new GetSuperGroups(UpdateAffiliationsPreferences.this, context, "Retrieving Group List...", this).execute();
        }

        public void onTaskCompleted(ArrayList<String> list) {
            Toast.makeText(getApplicationContext(), "hello from async", Toast.LENGTH_SHORT).show();
        }

    }

and

  public class GetSuperGroups extends AsyncTask<String, String, ArrayList<String>> {

        private Activity activity;
        private Context context;
        private String progressMsg;
        private ProgressDialog pDialog;
        private ArrayList<String> sg_list;
        private OnTaskCompleted listener;

        public GetSuperGroups(Activity activity, Context context, String progressMsg, OnTaskCompleted listener) {
            this.activity = activity;
            this.context = context;
            this.progressMsg = progressMsg;
            this.listener = listener;
        }
like image 53
Vipul Purohit Avatar answered Sep 23 '22 09:09

Vipul Purohit


You never call setSuperGroupList() so the listener remains null. Better to put listener into the constructor of your task.

like image 23
Alexander Kulyakhtin Avatar answered Sep 21 '22 09:09

Alexander Kulyakhtin