Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - result from AsyncTask not being returned to main Activity

I'm trying to use an AsyncTask-extended class to handle connecting to a URL, parsing JSON, displaying an indeterminate ProgressDialog during parsing, and returning the results as key-value pairs in a HashMap to the main Activity. The results of the HashMap will then be read by the main Activity and put into form fields. However, even though I'm populating the HashMap in my AsyncTask (evidenced by println statements), calling a method in the main Activity that returns the HashMap yields an empty result. I can't figure out if this is something I'm doing wrong, or if I'm misunderstanding the capabilities of AsyncTask.

I'm debating converting my class that extends AsyncTask to an Activity. Essentially, the user should not be able to do anything else during this data search/parsing and should wait until the ProgressDialog goes away before they can interact with the application again (or by hitting the back button). Also, my application needs to be able to handle certain cases in my AsyncTask where exceptions are caught (can't connect to URL, bad JSON, product ID to search by cannot be found) and custom error dialogs are tailored for those exceptions. I could easily do this if this class were an Activity, as I could send back different result codes when calling finish(), depending on if an exception is caught.

Again, I'm not sure if AsyncTask is the best solution here, since the user will not be doing anything else while the information is being gathered and parsed. Please advise me if a new Activity would make sense or if I'm just mangling my implementation of a background thread.

MainActivity.java

mInitiateProductLookupButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ProductLookup pl = new ProductLookup(id, MainActivity.this);
                pl.execute();

                // The below variable is always empty!
                HashMap<String, String> productInfo = pl.getProductInfo();
                applyProductInfoToFormFields(productInfo);
            }
        });

ProductLookup.java

public class ProductLookup extends AsyncTask<Object, Void, HashMap<String, String>> {
    private String mProductID;
    private Context mContext;
    HashMap<String, String> mProductInfo;
    ProgressDialog mDialog;

    public ProductLookup(String id, Context applicationContext) {
        mProductID = id;
        mContext = applicationContext;
        mProductInfo = new HashMap<String, String>();
    }

    @Override
    protected void onPreExecute() {
        mDialog = new ProgressDialog(mContext);
        mDialog.setMessage("Loading product info. Please wait...");
        mDialog.setIndeterminate(true);
        mDialog.setCancelable(false);
        mDialog.show();
    }

    @Override
    protected void onPostExecute(HashMap<String, String> result){
       super.onPostExecute(result);
       mDialog.dismiss();
       mProductInfo = result;
    }


    @Override
    protected HashMap<String, String> doInBackground(Object... params) {
        try {
            // Connect to URL, parse JSON, and add key-value pairs to mProductInfo...

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        finally {
            try {
                // Close input/output reader variables
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return mProductInfo;

    }

    public HashMap<String, String> getProductInfo(){
        return this.mProductInfo;
    }

}
like image 214
Keeb13r Avatar asked Dec 02 '10 07:12

Keeb13r


2 Answers

When you issue .execute() that runs as threaded and doesn't wait for the result.

So whatever you call after this it, is empty as the data has not been loaded yet.

You need to set on PostExecuted the result directly to your Activity via a setter MainActivity.this.setProductInfo(result)

like image 166
Pentium10 Avatar answered Nov 15 '22 16:11

Pentium10


There is some miss concept for you. The statement after AsyncTask.execute() will be executed just after the call. While your doInBackground is performing in other thread. Here, when you are using productInfo map, the doInBackground was not completed so result is not populated there

Easy solution for you is to use the result in the onPostExecute methord.

protected void onPostExecute(HashMap<String, String> result){
       mDialog.dismiss();
       mProductInfo = result;
 applyProductInfoToFormFields(productInfo);

    }
like image 23
Labeeb Panampullan Avatar answered Nov 15 '22 16:11

Labeeb Panampullan