【问题标题】:Very unusual error while dismissing ProgressDialog in AsyncTask在 AsyncTask 中关闭 ProgressDialog 时出现非常不寻常的错误
【发布时间】:2012-08-28 14:21:28
【问题描述】:

我开发了一个 Android 2.2 应用程序,但我只收到一次此错误:

java.lang.IllegalArgumentException: View not attached to window manager

当我关闭 ProgressDialog 时会发生此错误。这个dialogAsyncTask 上。这是我的代码:

private class LoadGatesAsyncTask extends AsyncTask<Void, Void, Boolean>
{
    private Context mContext;
    private ArrayList<Gate> mGatesList;
    private ProgressDialog mLoadingDialog;

    public LoadGatesAsyncTask(Context context)
    {
        this.mContext = context;
        mLoadingDialog = new ProgressDialog(mContext);
        mLoadingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        mLoadingDialog.setMessage(getString(R.string.msg_loading_gates));
        mLoadingDialog.setCancelable(false);
        mLoadingDialog.show();
    }

    @SuppressWarnings("unchecked")
    @Override
    protected Boolean doInBackground(Void... params)
    {
        Boolean result = false;

        try
        {
            [ ... ]
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
        return result;
    }

    @Override
    protected void onPostExecute(Boolean result)
    {
        super.onPostExecute(result);

        if (result)
        {
            [ ... ]

            mLoadingDialog.dismiss();
        }
        else
        {
            mLoadingDialog.dismiss();
            Toast toast = Toast.makeText(mContext,
                    getString(R.string.msg_error_loading_gates),
                    Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.CENTER, 
                    toast.getXOffset() / 2,
                    toast.getYOffset() / 2);

            toast.show();
        }
    }

}

如何以编程方式避免此错误?如果不是attached to window manager,我是否可以做任何检查以避免将其关闭?

【问题讨论】:

标签: android android-asynctask progressdialog


【解决方案1】:

您是否在 OnCreate 中实例化 LoadGatesAsyncTask?

如果是这样,请将 loadingDialog 实例化到 OnPreExecute 而不是在构造函数中。

【讨论】:

  • 不,它是在 onResume 上实例化的。
  • 只有在所有 Activity 都显示后才能附加窗口。这仅在 onresume 之后发生。所以只有在 Onresume 执行完成后才能显示对话框
【解决方案2】:

您可以添加支票:

if(mLoadingDialog.isShowing()){
   mLoadingDialog.dismiss();
}

【讨论】:

    【解决方案3】:

    您在构造函数中初始化此 ProgressDialog,而不是在 onPreExecute() 中,这是错误,因为您在 onPostExecute 中取消了 ProgressDialog,您需要在 相同 UI 线程。

    如果你初始化对象 - AsynTask,你会调用你的构造函数。所以你的ProgressDialog 会显示出来,但是你还没有在AsyncTask 上调用.execute()!因此,当您尝试关闭它时,编译器会发现自己位于不同的线程上。

    编辑:澄清被误解的陈述。

    【讨论】:

    • 确定构造函数没有和调用者在同一个线程中运行?如果是这样,我猜 onCreate() 会像 onPreExecute() 一样在 UI 线程中运行。
    • 错了?!如果我从 UI 线程构造 AsyncTask 对象,不要告诉我对象创建也不会在 UI 线程上!
    • 根据AsyncTask documentation中的threading rules你错了:The task instance must be created on the UI thread对不起。
    • you need to do it on the GUI thread aka - NOT in constructor 很难被误解。您建议构造函数不在 GUI 线程上。这是完全错误的!而你的完整答案只是关于 GUI 线程和构造函数......
    • 我没有回答这个问题。无论如何,您应该更仔细地阅读文档。也必须在 UI 线程上调用 execute()。仅仅因为稍后调用某些东西并不意味着它是从另一个线程调用的。您在答案中的最后一句话也是错误的。只有一个 UI 线程。您从同一个线程(始终是 UI 线程)调用构造函数、execute()、onPreExecute() 和 onPostExecute()! Execute() 在内部创建一个新线程并在该线程中运行 doInBackground()。我不确定你对线程有多熟悉,但你应该阅读更多关于 AsyncTask 的内容。
    【解决方案4】:

    我认为真正的问题在于progressDialog后面的附加Activity

    它正在更改为新的引用(实例),

    这样progressDialog.OwnerActivity=null(通常在轮换时调用onCreate)

    通过将新的重新创建的 Activity 附加到所有者来解决:progressDialog.OwnerActivity = myActivity;(它将在您的类中传递一个本地参数,在构造函数中传递它, like :(这里是C# android,类似于java..同样的想法)

    class ProgressDialogAsync: AsyncTask //extends asynctask
    {
    //used parameters
    
    Activity Activity;
    
    string Title;
    string Message;
    
    ProgressDialog AsyncDialog;
    
    public ProgressDialogAsync(Activity Activity, string Title, string Message)
     {    
      this.Title = Title;
      this.Message = Message;
      this.Activity = Activity;
     }
    
    
    protected override void OnPreExecute()
    {
     AsyncDialog = new ProgressDialog(Activity);
    }
    
    protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] @params)       {
     //do background operation
    }
    
    protected override void OnPostExecute(Java.Lang.Object result)
    {
     //do something
     AsyncDialog.OwnerActivity = Activity;
     AsyncDialog.Dismiss();
     base.OnPostExecute(result);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-12
      • 2012-08-05
      • 1970-01-01
      • 2010-11-15
      • 1970-01-01
      相关资源
      最近更新 更多