0
votes

Hi onCancel of dialog i want to cancel to server call but i m facing problem that even i cancel the task, it hits my server and modifies the data. How can I resolve this issue ? Below is my code..


     private class UserBoardingTask extends AsyncTask {
            @Override
            protected void onPreExecute() {
                progressDialog = new ProgressDialog(getActivity());
                progressDialog.setMessage(getResources().getString(R.string.please_wait));
                progressDialog.setIndeterminate(false);
                progressDialog.setCancelable(true);
                progressDialog.setOnCancelListener(new OnCancelListener() {
                @Override
                    public void onCancel(DialogInterface dialog) {
                         if (userOnBoardingTask!= null && userOnBoardingTask.getStatus() != AsyncTask.Status.FINISHED && !userOnBoardingTask.isCancelled()) {
                             userOnBoardingTask.cancel(true);

                           }      
                    }
                });
                progressDialog.show();
            }

            @Override
            protected Void doInBackground(String... urls) {
                String boardingURL=null;


                boardingURL= getUrl();


                UserOnBoardingDTO userOnBoardingDetailsDTO = AppStateManager.getUserBoardingDetails();
                try{

                    RestAPIManager.putToNSWebService(boardingURL, userOnBoardingDetailsDTO, username, password);

                }   


                   catch (Exception e) {
                   errorMessage=getResources().getString(R.string.unknown_exp);
                    }
                return null;
                }

            @Override
            protected void onCancelled() {
                super.onCancelled();
                closeProgressDialog();
                errorMessage="";
                AppStateManager.setUserBoardingDetails(null);
                userOnBoardingTask=null;

            }

            @Override
            protected void onPostExecute(Void res) {
                closeProgressDialog();
                userOnBoardingTask=null;
                if(!FieldsValidator.isBlank(errorMessage)){
                    CommonUtil.showToast(getActivity(),errorMessage);
                    errorMessage="";
                    return; 
                }

7

7 Answers

2
votes

Just check isCancelled() once in a while:

 protected Object doInBackground(Object... x) {
    while (/* condition */) {
      // work...
      if (isCancelled()) break;
    }
    return null;
 }

and another solution is

protected void onProgressUpdate(String... progress1) {
                         if(condition){

                                break;
                        }
        }
0
votes

Move the dialog out of the async task and only start the task when the dialog is not canceled.

0
votes

Actually the problem is not termination of your asynsTask but the server hit if a server hit is already done before termination of asynsTask then you must interrupt your server request also.Just terminate your server request using abort method.

0
votes

Where is userOnBoardingTask declared and where it is assigned to a reference to running task? I suspect this does not store a proper reference when the task tries to cancel it.

I am not sure if it is the actual reason of your problem. But for sure you may get rid of this variable if it is intended to pint at current task. Just change dialog's on cancel listener:

private class UserBoardingTask extends AsyncTask<String, Void, Void> {

@Override
protected void onPreExecute() {

    // ...

    progressDialog.setOnCancelListener(new OnCancelListener() {

        @Override
        public void onCancel(DialogInterface dialog) {
            if (UserBoardingTask.this.getStatus() != AsyncTask.Status.FINISHED 
                && UserBoardingTask.this.isCancelled()) {
                UserBoardingTask.this.cancel(true);
            }
        }
    });

In fact you may omit UserBoardingTask.this phrase as the inner class can point directly fields of nesting class as far as the names are not obscured by the names of inner class members:

private class UserBoardingTask extends AsyncTask<String, Void, Void> {

@Override
protected void onPreExecute() {

    // ...

    progressDialog.setOnCancelListener(new OnCancelListener() {

        @Override
        public void onCancel(DialogInterface dialog) {
            if (getStatus() != AsyncTask.Status.FINISHED && isCancelled()) {
                cancel(true);
            }
        }
    });

EDIT

Another point is that before sending request to the server you may check inside doInBackground you may check if the task has not been cancelled

        // ...

        @Override
        protected Void doInBackground(String... urls) {

            // ...

            try {
                if(isCancelled()) {
                   throw new Exception("Exit: task cancelled!");
                }

                RestAPIManager.putToNSWebService(boardingURL, userOnBoardingDetailsDTO, username, password);

            // ...
0
votes
RestAPIManager.putToNSWebService(boardingURL, userOnBoardingDetailsDTO, username, password);

This above code hit the server. So you have to validate the execution of code inbetween cancellation.

Try something like this

  try{
if(!userOnBoardingTask.isCancelled())
{
                RestAPIManager.putToNSWebService(boardingURL, userOnBoardingDetailsDTO, username, password);
}

            }   


               catch (Exception e) {
               errorMessage=getResources().getString(R.string.unknown_exp);
                }

This is ok. If user cancel the task before ResetAPIManager code executes. Suppose user try to cancel the task after server call initiated you have to tell already modified or remodify server data or unable to cancel or some message to user. All done through getting server reponse and validate server response if it changed or not.

Use something like this

 Var rsponse = RestAPIManager.putToNSWebService(boardingURL,userOnBoardingDetailsDTO, username, password);

Validate the reponse message in onPostExecute() or OnCancelled() method.

0
votes

If you cancel the asynctask after access this method RestAPIManager.putToNSWebService(boardingURL,userOnBoardingDetailsDTO, username, password); the async task will cancel after running the above code so you should correct this by creating a new method inside RestAPIManager class and call that method inside OnCancelled method from your asyncTask.

0
votes

Short Anser: Its not possible stop data posts thru a simple cancel. once an async task runs even if you cancel it mid way data posts will occure. Cancellation can be done in a Simple Run Check this Post [Android - Cancel AsyncTask Forcefully