【问题标题】:Cannot show ProgressDialog from AsyncTask : Can't create handler inside thread that has not called Looper.prepare()无法从 AsyncTask 显示 ProgressDialog:无法在未调用 Looper.prepare() 的线程内创建处理程序
【发布时间】:2012-12-14 04:23:35
【问题描述】:

我有一种情况,用户点击特定按钮,我的应用程序中会显示一个对话框主题活动。由于第二个活动(对话框活动)的内容是使用HttpRequest 获取的,因此我希望用户在加载对话框之前看到ProgressDialog

AsyncTask 似乎是用于此目的的最佳选择。因此,我编写了以下课程。

public class DetailsList extends AsyncTask<String, Integer, String> {

public static final String LOG_TAG = "DetailsList";
private Context context;
private ProgressDialog dialog;
private Activity activity;

public DetailsList(Context context) {
    this.context = context;
}

public DetailsList(Activity activity) {
    this.activity = activity;
}

@Override
protected void onPreExecute() {
    dialog = new ProgressDialog(this.context);
    dialog.setMessage("Loading...");
    dialog.setCanceledOnTouchOutside(false);
}

@Override
protected void onPostExecute(String result) {
    if(dialog.isShowing()) {
        dialog.dismiss();
    }
}

@Override
protected String doInBackground(String...params) {
    this.publishProgress(100);
    Log.d(LOG_TAG, "doInBackground started.");
    JSONObject requestContent = new JSONObject();
    JSONObject detailViewResponse = new JSONObject();
    try {
        requestContent.put("serviceId", params[0]);
        APIRequest detailViewAPI = new APIRequest(
                "http://" + GeneralConstants.SERVER_ADDRESS + "/services/",
                requestContent
                );
        detailViewResponse = detailViewAPI.request();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return detailViewResponse.toString();
}

@Override
protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
    dialog.show();
}

}

当进行 get 调用时,我有以下异常堆栈跟踪:

12-29 05:12:29.149: W/System.err(3459): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
12-29 05:12:29.159: W/System.err(3459):     at android.os.Handler.<init>(Handler.java:121)
12-29 05:12:29.159: W/System.err(3459):     at android.app.Dialog.<init>(Dialog.java:112)
12-29 05:12:29.159: W/System.err(3459):     at android.app.AlertDialog.<init>(AlertDialog.java:114)
12-29 05:12:29.159: W/System.err(3459):     at android.app.AlertDialog.<init>(AlertDialog.java:98)
12-29 05:12:29.164: W/System.err(3459):     at android.app.ProgressDialog.<init>(ProgressDialog.java:77)
12-29 05:12:29.164: W/System.err(3459):     at threads.DetailsList.<init>(DetailsList.java:30)
12-29 05:12:29.164: W/System.err(3459):     at app.command.DetailViewDisplayCommand.execute(DetailViewDisplayCommand.java:54)
12-29 05:12:29.164: W/System.err(3459):     at commands.Command.execute(Command.java:32)
12-29 05:12:29.164: W/System.err(3459):     at gl.ObjectPicker.findObjectForValue(ObjectPicker.java:92)
12-29 05:12:29.164: W/System.err(3459):     at gl.ObjectPicker.pickObject(ObjectPicker.java:58)
12-29 05:12:29.164: W/System.err(3459):     at gl.GL1Renderer.onDrawFrame(GL1Renderer.java:111)
12-29 05:12:29.164: W/System.err(3459):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1520)
12-29 05:12:29.164: W/System.err(3459):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1244)

似乎错误是从我初始化对话框的那一行触发的。

dialog = new ProgressDialog(this.context);

【问题讨论】:

  • 尝试将这一行 dialog = new ... 放在 this.context = context; 之后的类构造函数中,而不是放在 onPreExecute
  • @A--C 你是如何修复日志的?使用了什么格式?
  • @mahesmohan 奇怪的是,这次它没有得到很好的修复,但是如果你突出显示文本然后单击花括号,它会变成一个代码块。 SO通常擅长确定接下来要应用哪种格式。
  • @La 我试过了。还是一样的错误。
  • @A--C 谢谢。请记住这一点。

标签: android android-asynctask progressdialog


【解决方案1】:
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1244)

AsyncTask 旨在防止主线程因繁重的操作而变慢。但是,您不在主线程上,而是在 OpenGL 线程上。我自己没有尝试过,但是会发生什么:

@Override
protected void onPreExecute() {
    Looper.prepare();
    Looper.loop();
    dialog = new ProgressDialog(this.context);
    dialog.setMessage("Loading...");
    dialog.setCanceledOnTouchOutside(false);
}

@Override
protected void onPostExecute(String result) {
    if(dialog.isShowing()) {
        dialog.dismiss();
    }
    Looper.quit();
}

(这可能有效,也可能会引发尝试从错误的线程异常访问 UI。)

【讨论】:

  • 由于构造函数中发生异常,我怀疑您对onPreExecute() 的修改是否会有所帮助。但是 +1 是为了抓住 GLThread,因为我已经错过了。
  • @Sam Looper 确实有效。没有例外,但 AsyncTask 仍然没有被执行。也不抛出异常。
  • 将 prepare 和 loop 方法放在正确的位置可以解决关于 GLThread 的问题。但仍然没有 ProgressDialog。
  • @mahesmohan 尝试在onPreExecute() 中调用dialog.show(),但如果任务立即完成,您将看不到ProgressDialog。
猜你喜欢
  • 2011-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-28
  • 2017-03-07
  • 2014-11-04
  • 2011-09-06
相关资源
最近更新 更多