在AsyncTask中为ProgressDialog创建处理程序时,无法在未调用Looper.prepare()的线程内创建处理程序。

78

我不明白为什么会出现这个错误。我正在使用AsyncTask在后台运行一些进程。

我有:

protected void onPreExecute() 
{
    connectionProgressDialog = new ProgressDialog(SetPreference.this);
    connectionProgressDialog.setCancelable(true);
    connectionProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    connectionProgressDialog.setMessage("Connecting to site...");
    connectionProgressDialog.show();

    downloadSpinnerProgressDialog = new ProgressDialog(SetPreference.this);
    downloadSpinnerProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    downloadSpinnerProgressDialog.setMessage("Downloading wallpaper...");
}

当我进入doInBackground()时,根据条件:

[...]    
connectionProgressDialog.dismiss();
downloadSpinnerProgressDialog.show();
[...]
无论何时我尝试使用downloadSpinnerProgressDialog.show(),都会收到错误信息。
有什么想法吗?
4个回答

106

show()方法必须从用户界面(UI)线程中调用,而doInBackground()在不同的线程上运行,这也是为什么设计了AsyncTask的主要原因。

你必须在onProgressUpdate()onPostExecute()中调用show()

例如:

class ExampleTask extends AsyncTask<String, String, String> {

    // Your onPreExecute method.

    @Override
    protected String doInBackground(String... params) {
        // Your code.
        if (condition_is_true) {
            this.publishProgress("Show the dialog");
        }
        return "Result";
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        connectionProgressDialog.dismiss();
        downloadSpinnerProgressDialog.show();
    }
}

3
对我来说那并没有起作用,我刚试了一下 "AlertDialog.Builder builder = new AlertDialog.Builder(context);" 并添加了构建器的配置。尝试在 onProgressUpdate 中展示它会导致完全相同的错误。有什么想法吗? - ins0m
谢谢Konstantin,我之前不知道可以使用publishProgress()来覆盖onProgressUpdate并使用任何变量类型。这真的帮了我很多,可以通过toast消息简单地更新进度。 - wired00

81

我遇到了类似的问题,但从阅读这个问题中,我发现我可以在UI线程上运行:

YourActivity.this.runOnUiThread(new Runnable() {
    public void run() {
        alertDialog.show();
    }
});

这对我来说似乎起作用了。


getActivity().runOnUiThread(this::mymethod); 运行得非常好,谢谢。 - mortezahosseini

1

我也曾经遇到过这个问题,对我来说解决方案是同时使用hyui和konstantin的答案。

class ExampleTask extends AsyncTask<String, String, String> {

// Your onPreExecute method.

@Override
protected String doInBackground(String... params) {
    // Your code.
    if (condition_is_true) {
        this.publishProgress("Show the dialog");
    }
    return "Result";
}

@Override
protected void onProgressUpdate(String... values) {

    super.onProgressUpdate(values);
    YourActivity.this.runOnUiThread(new Runnable() {
       public void run() {
           alertDialog.show();
       }
     });
 }

}

我以为在 onProgressUpdate() 中完成的工作会自动在 UI 线程上运行。 - Someone Somewhere

0
final Handler handler = new Handler() {
        @Override
        public void handleMessage(final Message msgs) {
        //write your code hear which give error
        }
        }

new Thread(new Runnable() {
    @Override
    public void run() {
    handler.sendEmptyMessage(1);
        //this will call handleMessage function and hendal all error
    }
    }).start();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接