【问题标题】:How to show ProgressDialog after AlertDialog如何在 AlertDialog 之后显示 ProgressDialog
【发布时间】:2012-09-18 19:42:14
【问题描述】:

我无法隐藏一个警告对话框。

当用户按下按钮时,我会显示一个使用此代码创建的对话框:

new AlertDialog.Builder(this)
            .setTitle(R.string.enterPassword)                
            .setView(textEntryView)          
            .setPositiveButton(R.string.ok, 
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            String password = pwdText.getText().toString();
                            dialog.dismiss();
                            processUserAction(password,targetUri);
                        }
                    })
            .setNegativeButton(R.string.cancel, 
                    new DialogInterface.OnClickListener() {                    
                        public void onClick(DialogInterface dialog, int whichButton) {
                            }                
                        })             
            .
            create();

在“processUserAction”方法中执行了一些繁重的操作,在其中我使用了一个显示 ProgressDialog 的 AysncTask。

我遇到的问题是提示输入密码的对话框永远不会出现在屏幕上(我尝试过用dismiss()、cancel())。 我猜它会一直留在那里直到 onClick 方法完成。

那么,我的问题是如何关闭该 AlertDialog,以便显示 ProgressDialog?

我一直在尝试的另一种方法是在 AlertDialog 中设置 DismissListener 并从那里调用繁重的操作,但我没有运气(它没有被调用)。

编辑:添加 AsyncTask 代码

public class BkgCryptOperations extends AsyncTask<File,Void,Integer>{

    @Override
    protected Integer doInBackground(File... files) {
        if (files!=null && files.length > 0){
            File source = files[0];
            File target = files[1];
            return cryptAction.process(source,password, target);
        }

        return Constants.RetCodeKO;
    }

    CryptAction cryptAction;
    String password;
    ProgressDialog progressDialog;


    public BkgCryptOperations (CryptAction cryptAction,String password,ProgressDialog progressDialog){
        this.cryptAction=cryptAction;
        this.password=password;
        this.progressDialog=progressDialog;
    }

    @Override
    protected void onPreExecute() {
        if (progressDialog!=null){
            progressDialog.show();
        }
    }
    protected void onPostExecute(Integer i) {
        if (progressDialog!=null){
            progressDialog.dismiss();
        }
    }


}

提前致谢

【问题讨论】:

  • 你在调用 dialog.show() 吗?当然,你必须调用它来显示一个对话框。如果是,您能否修改代码以使其更清晰。
  • 是的,我在创建 dialog.show() 后立即调用它。你要我澄清哪一部分?我认为我的 setPositiveButton onClickListener 部分有问题。
  • 您是否尝试过在 Activity 中定义静态 AlertDialog,然后从 onClick() 事件中直接通过其名称将其关闭(而不是使用该 DialogInterface 实例)?
  • 您的意思是在 Activity 中引用 AlertDialog 并在该引用上执行关闭,对吗?我会检查并更新。感谢您的建议。

标签: java android android-asynctask android-alertdialog progressdialog


【解决方案1】:

以下是我的示例:

public void daten_remove_on_click(View button) {
        // Nachfragen
        if (spinadapter.getCount() > 0) {
            AlertDialog Result = new AlertDialog.Builder(this)
                    .setIcon(R.drawable.icon)
                    .setTitle(getString(R.string.dialog_data_remove_titel))
                    .setMessage(getString(R.string.dialog_data_remove_text))
                    .setNegativeButton(getString(R.string.dialog_no),
                            new DialogInterface.OnClickListener() {
                                public void onClick(
                                        DialogInterface dialogInterface, int i) {
                                    // Nicht löschen
                                    dialogInterface.cancel();
                                }
                            })
                    .setPositiveButton(getString(R.string.dialog_yes),
                            new DialogInterface.OnClickListener() {
                                public void onClick(
                                        DialogInterface dialogInterface, int i) {
                                    String _quellenName = myCursor.getString(1);
                                    deleteQuellenRecord(_quellenName);
                                    zuletztGelöscht = _quellenName;
                                }
                            }).show();
        } else {
            // Keine Daten mehr vorhanden
            Toast toast = Toast.makeText(Daten.this,
                    getString(R.string.dialog_data_remove_empty),
                    Toast.LENGTH_SHORT);
            toast.show();
        }
    }

这里是deleteQuellenRecord的代码:

private void deleteQuellenRecord(String _quellenName) {
        String DialogTitel = getString(R.string.daten_delete_titel);
        String DialogText = getString(R.string.daten_delete_text);
        // Dialogdefinition Prograssbar
        dialog = new ProgressDialog(this) {
            @Override
            public boolean onSearchRequested() {
                return false;
            }
        };
        dialog.setCancelable(false);
        dialog.setTitle(DialogTitel);
        dialog.setIcon(R.drawable.icon);
        dialog.setMessage(DialogText);
        // set the progress to be horizontal
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        // reset the bar to the default value of 0
        dialog.setProgress(0);
        // set the maximum value
        dialog.setMax(4);
        // display the progressbar
        increment = 1;
        dialog.show();
        // Thread starten
        new Thread(new MyDeleteDataThread(_quellenName)) {
            @Override
            public void run() {
                try {
                    // Datensatz löschen
                    myDB.execSQL("DELETE ... ');");
                    progressHandler
                            .sendMessage(progressHandler.obtainMessage());
                    myDB.execSQL("DELETE ...);");
                    // active the update handler
                    progressHandler
                            .sendMessage(progressHandler.obtainMessage());
                    myDB.execSQL("DELETE ...;");
                    // active the update handler
                    progressHandler
                            .sendMessage(progressHandler.obtainMessage());
                    // Einstellung speichern
                    try {
                        settings.edit().putString("LetzteQuelle", "-1")
                                .commit();
                    } catch (Exception ex) {
                        settings.edit().putString("LetzteQuelle", "").commit();
                    }

                } catch (Exception ex) {
                    // Wait dialog beenden
                    dialog.dismiss();
                    Log.e("Glutenfrei Viewer",
                            "Error in activity MAIN - remove data", ex); // log
                                                                            // the
                                                                            // error
                }
                // Wait dialog beenden
                dialog.dismiss();

            }
        }.start();
        this.onCreate(null);
    }

使用异步任务我这样做:

private class RunningAlternativSearch extends
            AsyncTask<Integer, Integer, Void> {


        final ProgressDialog dialog = new ProgressDialog(SearchResult.this) {
            @Override
            public boolean onSearchRequested() {
                return false;
            }
        };



        @Override
        protected void onPreExecute() {
            alternativeSucheBeendet = false;
            String DialogTitel = getString(R.string.daten_wait_titel);
            DialogText = getString(R.string.dialog_alternativ_text);
            DialogZweiteChance = getString(R.string.dialog_zweite_chance);
            DialogDritteChance = getString(R.string.dialog_dritte_chance);
            sucheNach = getString(R.string.dialog_suche_nach);
            dialog.setCancelable(true);
            dialog.setTitle(DialogTitel);
            dialog.setIcon(R.drawable.icon);
            dialog.setMessage(DialogText);
            dialog.setOnDismissListener(new OnDismissListener() {
                public void onDismiss(DialogInterface arg0) {
                    // TODO Auto-generated method stub
                    cancleBarcodeWorker();
                    if (alternativeSucheBeendet==false){
                        // Activity nur beenden wenn die Suche
                        // nicht beendet wurde, also vom User abgebrochen
                        Toast toast = Toast.makeText(SearchResult.this, SearchResult.this
                                .getString(R.string.toast_suche_abgebrochen),
                                Toast.LENGTH_LONG);
                        toast.show();
                        myDB.close();
                        SearchResult.this.finish();
                    }
                }
            });
            dialog.show();
        }


        ...

【讨论】:

  • 和 Aaron 提案一样,我会尝试更新,但乍一看我看不出有什么不同,因为 onClink 方法在处理繁重的操作时仍然会被执行。感谢您的建议。
  • 我已经更新了答案。 deleteQuellenRecord 是一个显示进度条的长时间运行的任务。奇怪的是,我从不调用 Result.dismiss() 或 Result.cancle() 但对话框消失了,进度条出现在前面。也许它有助于删除行 dialog.dismiss() 或将其更改为 cancle()
  • 我之前没有dismiss() 或cacncel(),我只是把它放在那里,因为我读到它们应该可以工作。您是如何执行 deleteQuellenRecord 中长时间运行的任务的?使用异步任务?还是只是创建自己的线程?
  • 添加了异步任务的示例。希望对你有帮助
  • 感谢您的示例,我将其更改为使用 Thread 方法而不是 AsyncTask,正如 licabl 所提出的那样。当我可以测试它时,我会更新,但这需要一些时间,因为我现在做不到。
【解决方案2】:

你能显示 processUserAction(..) 的代码吗?没有必要包括解雇。 我做了一些非常相似的事情,没有任何问题...... 代码如下:

AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Export data.\nContinue?")
            .setCancelable(false)
            .setPositiveButton("Yes",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            String file = getObra().getNome();
                            d = new ProgressDialog(MenuActivity.this);
                            d.setTitle("Exporting...");
                            d.setMessage("please wait...");
                            d.setIndeterminate(true);
                            d.setCancelable(false);
                            d.show();
                            export(file);
                        }
                    })
            .setNegativeButton("No",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    });
    AlertDialog alert = builder.create();
    alert.show();

在 export(file) 中我打开线程:

private void export(final String file) {


    new Thread() {
        public void run() {
            try {
                ExportData ede = new ExportData(
                        getApplicationContext(), getPmo().getId(),
                        file);
                ede.export();
                handlerMessage("Done!!");
            } catch (Exception e) {
                handlerMessage(e.getMessage());
                System.out.println("ERROR!!!" + e.getMessage());
            }
        }
    }.start();
}

在 handlerMessage 中,我关闭了 progressDialog 并显示最终消息。 希望对你有帮助。

【讨论】:

  • 我可以添加 processUserAction 方法,但它只会使事情变得混乱。它工作正常,但在执行 4-5 秒期间,我只看到应用程序顶部的 AlertDialog(这就是我遇到的问题,它不太友好)。此时也无法点击。您建议的方法与我使用的 AsyncTask 不同,我会尝试并更新。感谢您的建议。
【解决方案3】:

您可以在 AlertDialog 之外创建一个侦听器,以抽象出 OnClickListener 中肯定按钮的逻辑。这样,可以通知侦听器,并且 AlertDialog 将立即关闭。然后,对来自 AlertDialog 的用户输入的任何处理都可以独立于 AlertDialog 进行。我不确定这是否是实现这一目标的最佳方式,但过去对我来说效果很好。

据我所知,我没有发现您的 AsyncTask 代码有任何明显的问题。

public interface IPasswordListener {
    public void onReceivePassword(String password);
}

IPasswordListener m_passwordListener = new IPasswordListener {
    @Override
    public void onReceivePassword(String password) {
        processUserAction(password,targetUri);
    }
}

public void showPasswordDialog() {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle(R.string.enterPassword);
    builder.setView(textEntryView);
    builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            m_passwordListener.onReceivePassword(pwdText.getText().toString());
            dialog.dismiss();
        }
    });
    builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            dialog.cancel();
        }
    });
    builder.show();
}

【讨论】:

  • 我会尝试更新,但乍一看我看不出有什么不同,因为 onClink 方法在处理繁重的操作时仍然会被执行。感谢您的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-17
  • 1970-01-01
  • 2020-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多