KaHeL
KaHeL

Reputation: 4371

Android Class with sub-class AsyncTask wait for the postExecute before returning the value

currently I'm doing something for my project wherein I created a separate Class that will only handle the Asynctask and get the value of the webservices I passed and that class should return the JSON response as a String. Now I already achieved it using taskName.execute().get(); wherein it will wait for the task to complete but the problem is it is also waiting for the task to complete before displaying the screen layout. Making my progressDialog useless and cause a delay on switching screens. Here's my code for now:

For the Class with AsyncTask:

public class UtilGetResponse {

    Context context;
    Map hash_values = new HashMap();
    int DialogType;
    String response;
    /*  
        PLAN FOR DialogTypes:
    * 0 - Standard Please wait dialog
    * 1 - Progress dialog
    * 2 - Camera upload dialog
    * */


    InputStream is = null;
    StringBuilder string_builder = null;


    public UtilGetResponse(Map values, Context baseContext, int type){
        /*initialize class and pass the hash values for parameters*/
        context = baseContext;
        hash_values.putAll(values);
        DialogType = type;
    }

    public String startTask(){
        //TODO CASE WHEN BASED ON THE DIALOG TYPE SPECIFIED
        Utilities util = new Utilities();

        if(util.isOnline(context)){
            try {
                new UploaderTaskStandard().execute().get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        return response; //THE RESPONSE ONLY SHOW ONCE THE WHOLE TASK IS COMPLETED
    }


    public class UploaderTaskStandard extends AsyncTask<Map, Void, Void> {
        ProgressDialog simpleDialog;

        @Override
        protected void onPreExecute() {
            /*Do something before the async task starts*/
            simpleDialog = new ProgressDialog(context);
            simpleDialog.setMessage("Please wait");
            simpleDialog.show();
        }

        @Override
        protected Void doInBackground(Map... maps) {
            uploadData();
            return null;
        }

        protected void onPostExecute(Void v) {
            /*Do something after the task is complete*/
            simpleDialog.dismiss();
        }
    }

    private void uploadData() {
        response = "null";
        String url = hash_values.get("url").toString().replace(" ", "%20"); //get the URL replacing the space with %20

        //If the user is trying to upload a file use this part
        try {
            HttpClient client = new DefaultHttpClient();
            HttpPost post = new HttpPost(url);
            MultipartEntity mpEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);

                /*This will convert the hashMap sent into individual part per key per value*/
            Set set = hash_values.entrySet();
            Iterator iterator = set.iterator();

                /*do a loop passing all the data on a string*/
            while(iterator.hasNext()) {
                Map.Entry mapEntry = (Map.Entry)iterator.next();
                String keyword = String.valueOf(mapEntry.getKey());
                String value = String.valueOf(mapEntry.getValue());

                    /*this will check if the passed data is a URL, file or a simple value*/
                if(!keyword.equals("url")){
                    if(value.matches("(.*)/(.*)")){
                        File file = new File(value);
                        Log.v("Does this exists?",String.valueOf(file.exists()));
                        if(file.exists()){
                            FileBody upload_file;
                            upload_file = new FileBody(file);
                                /*not url but file*/
                            mpEntity.addPart(keyword, upload_file);
                        }else{
                                /*not url and not file*/
                            mpEntity.addPart(keyword, new StringBody(value));
                        }
                    }else{
                            /*not URL and not file*/
                        mpEntity.addPart(keyword, new StringBody(value));
                    }
                }
            }

            post.setEntity(mpEntity);
            HttpResponse response = client.execute(post);
            HttpEntity resEntity = response.getEntity();

            is = resEntity.getContent();
        } catch (Exception e) {
            e.printStackTrace();
            response = "null";
        }

        /*convert JSON to string*/
        try{
            BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
            string_builder = new StringBuilder();
            String line = "0";

            while ((line = reader.readLine()) != null) {
                string_builder.append(line + "\n");
            }
            is.close();
            response = string_builder.toString();
        }catch(Exception e){
            e.printStackTrace();
        }

    }

}

And to call this:

Map hash_values = new HashMap();

        try{
            HashMap params = new HashMap<String,String>();
            params.put("param1", "YOUR_PARAM");
            params.put("url", "YOUR_WEBSERVICE_URL");

            //pass parameters
            hash_values.putAll(params);
            //start async task

            UtilGetResponse util = new UtilGetResponse(hash_values, getActivity(), 0);
            String result = util.startTask();

            Log.v("The result string",result);

        }catch (Exception e){
            e.printStackTrace();
            e.getCause();
            Toast.makeText(getActivity(), "Oops problem", Toast.LENGTH_SHORT).show();
        }

Is there's a way for me to do this properly without really waiting for the whole task to finish before moving to the next screen? I'm thinking of using a Handler but I'm not really familiar on how to use it anyway.

Upvotes: 0

Views: 385

Answers (1)

Techfist
Techfist

Reputation: 4344

Your issue is with usage of this

new UploaderTaskStandard().execute().get();

Although you using AsynTask, but still making system wait until result which is against your requirement, what you need is a delivery mechanism, which will notify you back once results are ready. You can take either of two approaches.

change to this, and implement one of below mechanism.
new UploaderTaskStandard().execute();
  1. Implementing handler, and posting result back once result available.
  2. Implementing observer design pattern, where you create an interface with methods such as onResultReady, and passing an object of class implementing above interface to your method startTask, and posting result back from AsyncTask onPostExecute once it is available via interface mechanism.

Going via interface will be very easy and in this way your code will be independent of your network logic, sample code below

// Observer listener interface design
interface ResultListener{
    // You can overload this method with data type you want to return
    public void onResultReceived();

    // Use them in a proper way for sending error message back to your program
    public void onTaskCancelled();
    public void onError();

}
 // This will be your new method signature
 public String startTask(ResultListener listener){
     // Call it liske this, passing listener reference
     new UploaderTaskStandard().execute(listener);
 }

 // This is your AsyncTask model
 public class UploaderTaskStandard extends AsyncTask<ResultListener, Void, Void> {

     ResultListener listener;

        @Override
        protected Void doInBackground(ResultListener... maps) {
            this.listener = maps[0];
            uploadData();
            return null;
        }

        protected void onPostExecute(Void v) {
            /*Do something after the task is complete*/
            simpleDialog.dismiss();
            // Notify back to calling program
            listener.onResultReceived();
        }

 }

Upvotes: 3

Related Questions