Android Back Button and Progress Dialog

那年仲夏 提交于 2019-12-02 16:37:18
user634618

First, you should show your dialog from OnPreExecute, hide it in OnPostExecute, and - if necessary - modify it by publishing progress. (see here)

Now to your question: ProgressDialog.show() can take a OnCancelListener as an argument. You should provide one that calls cancel() on the progress dialog instance.

example:

    @Override
    protected void onPreExecute(){
        _progressDialog = ProgressDialog.show(
                YourActivity.this,
                "Title",
                "Message",
                true,
                true,
                new DialogInterface.OnCancelListener(){
                    @Override
                    public void onCancel(DialogInterface dialog) {
                        YourTask.this.cancel(true);
                        finish();
                    }
                }
        );
    }

where _progressDialog is a ProgressDialog member of YourTask.

This class was deprecated in API level 26. ProgressDialog is a modal dialog, which prevents the user from interacting with the app. Instead of using this class, you should use a progress indicator like ProgressBar, which can be embedded in your app's UI. Alternatively, you can use a notification to inform the user of the task's progress. LINK

This can be achieved by the following code fragment:

progress.setCancelable(true);
progress.setCanceledOnTouchOutside(false);

progress is the ProgressDialog object...

This will enable the back button to close the dialog but prevent any touch input to do that...

Farhan

Well, I had the same issue. The simplest method that worked for me is using progressDialog.setCancelable(true).. This declares whether the dialog is cancelable by hitting the back key.. Try it and let me know if it works for you or not. Good luck

I just found a perfect and simplest solution to this problem. There's a method in ProgressDialog to set KeyListener.

progressDialog.setOnKeyListener(new OnKeyListener() {
    @Override
    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
        if(keyCode==KeyEvent.KEYCODE_BACK && !event.isCanceled()) {
            if(progressDialog.isShowing()) {
                //your logic here for back button pressed event
            } 
            return true;
        }
        return false;
    }
});

It's working fine with setCancelable(false). I am also checking for event.isCanceled(), because without that I was getting two events. I've tested this on Lollipop device with and without Hardware keys.

Treating back button like a cancellation is not the correct way.
Cancellation also occurs when a user touches the screen outside of the dialog box. You want to differentiate those two actions, no?

Correct approach would be to extend the ProgressDialog class and override the onBackPressed method.

private class SubProgressDialog extends ProgressDialog {
    public SubProgressDialog(Context context) {
        super(context);
    }
    @Override
    public void onBackPressed() {
        /** dismiss the progress bar and clean up here **/
    }
}


public void displayProgressBar(){
    progressBar = new SubProgressDialog(this);
    progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    progressBar.setCancelable(false);
    progressBar.setMessage(getString(R.string.authorizing));        
    progressBar.show();   
    new Thread(new Runnable() {
      public void run() {
      }
       }).start();     

}

Notice the setCancelable(false), again emphasizing that back button is different than a simple cancellation.
Also this will effecitvely ignore any other touch inputs from the user.

ofermc

Here's my solution to this. The PD problem occurs only when the app exiting on back button (Usually when the user presses it repetitively, and only sometimes (not all the times) the PD is called when the app already destroyed. Dismissing the PD onDestroy doesn't work for some reason and when I've tried it, each Back button press would close the app although canGoBack() was set to true. Instead I dismiss the PD on goBack which is the event that causes the collision in the first place, and I do it right before finish(). If the app exits on goBack normally there's no problem in the first place.

BTW, 'difference' is aimed to let the user to exit the app with a fast double click (400 MS between two clicks) instead of going back from page to page.

Hope it helps someone...

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (event.getAction() == KeyEvent.ACTION_DOWN) {
        switch (keyCode) {
        case KeyEvent.KEYCODE_BACK:
            difference = System.currentTimeMillis() - startTime;
            if (wView.canGoBack() && difference > 400) {
                wView.goBack();
            } else {
                dismissProgressDialog();
                finish();
            }
            startTime = System.currentTimeMillis();
            return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}


private void dismissProgressDialog() {
   if (progressDialog != null && progressDialog.isShowing()) {
        progressDialog.dismiss();
   }
}

javano... I tested your scenario using standard techniques, asyncTask and ProgressDialog. In my test, when the progressDialog is showing and i hit back, the progressdialog is dismissed and the background thread continues to run. I do not know why you need to call runOnUiThread.

SO:

show the progressDialog in onPreExecute place the long running task in doInBackground dismiss the progressDialog in onPostExecute pass the input parameters to your long running task as in:

new MyAsynch().execute(password,inString);

cancel() the asynchTask and progressDialog in onPause

protected void onPause() {
    super.onPause();
    if (asynch != null) {asynch.cancel(true);}
    if (progress != null){progress.cancel();}
}

JAL

I have some code here.

Its very simple just copy the below code and paste within Async task..

ProgressDialog dialog;

@Override
protected void onPreExecute() {

    dialog = new ProgressDialog(MainActivity.this) {
        @Override
        public void onBackPressed() {
            dialog.cancel();
            dialog.dismiss();
        }
    };
    // dialog.setTitle("file is..");//its optional If u want set title in progress
    // bar
    dialog.setMessage("Loading file....");
    dialog.setCancelable(false);

    dialog.show();

}

Please follow this, it shows the cancel button only async and finish will call by clicking on cancel button

protected void onPreExecute() {


        dialogx.setMessage("Loading... Please Wait...");
        dialogx.setCancelable(false);
        dialogx.setButton(DialogInterface.BUTTON_NEGATIVE,
                "Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

                dialogx.dismiss();
                GetDataTask.this.cancel(true);
                finish();
            }
        });
        dialogx.show();


    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!