我有一个启动AsyncTask的活动,并显示操作持续时间的进度对话框 . 声明活动不会通过旋转或键盘滑动重新创建 .
<activity android:name=".MyActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation"
>
<intent-filter>
</intent-filter>
</activity>
任务完成后,我会忽略对话框,但在某些手机上(框架:1.5,1.6)会抛出这样的错误:
java.lang.IllegalArgumentException: View not attached to window manager
at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:356)
at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:201)
at android.view.Window$LocalWindowManager.removeView(Window.java:400)
at android.app.Dialog.dismissDialog(Dialog.java:268)
at android.app.Dialog.access$000(Dialog.java:69)
at android.app.Dialog$1.run(Dialog.java:103)
at android.app.Dialog.dismiss(Dialog.java:252)
at xxx.onPostExecute(xxx$1.java:xxx)
我的代码是:
final Dialog dialog = new AlertDialog.Builder(context)
.setTitle("Processing...")
.setCancelable(true)
.create();
final AsyncTask<MyParams, Object, MyResult> task = new AsyncTask<MyParams, Object, MyResult>() {
@Override
protected MyResult doInBackground(MyParams... params) {
// Long operation goes here
}
@Override
protected void onPostExecute(MyResult result) {
dialog.dismiss();
onCompletion(result);
}
};
task.execute(...);
dialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface arg0) {
task.cancel(false);
}
});
dialog.show();
从我所阅读的内容(http://bend-ing.blogspot.com/2008/11/properly-handle-progress-dialog-in.html)和在Android源代码中看到,看起来唯一可能的情况是获取该异常是在活动被销毁时 . 但正如我所提到的,我禁止基本活动的活动娱乐 .
所以任何建议都非常感谢 .
15 回答
当我从onPostExecute方法中解除对话并完成活动时,我也得到此错误 sometimes . 我猜有时活动会在对话成功解散之前完成 .
简单而有效的解决方案对我有用
我可能有一个解决方法 .
有同样的问题,我通过
AsyncTask
将很多项目(通过文件系统)加载到ListView
. 如果onPreExecute()
触发ProgressDialog
,然后onPostExecute()
和onCancelled()
(当任务被AsyncTask.cancel()
明确取消时调用)通过.cancel()
关闭它 .当我在
AsyncTask
的onCancelled()
方法中杀死对话框时出现了相同的"java.lang.IllegalArgumentException: View not attached to window manager"错误(我在优秀的Shelves app中看到了这一点) .解决方法是在
AsyncTask
中创建一个包含ProgressDialog
的公共字段:然后,在
onDestroy()
当我取消AsyncTask
时,我也可以通过以下方式终止相关的对话框:调用
AsyncTask.cancel()
DOES在AsyncTask
中触发onCancelled()
,但由于某种原因,在调用该方法时,View已被销毁,因此取消对话框失败 .这是我的“防弹”解决方案,它汇集了我在这个主题上找到的所有好答案(感谢@Damjan和@Kachi) . 只有在所有其他检测方法都没有成功的情况下才会吞下异常 . 在我的情况下,我需要自动关闭对话框,这是保护应用程序免于崩溃的唯一方法 . 我希望它会对你有所帮助!如果您有备注或更好的解决方案,请投票并留下评论 . 谢谢!
以下是解决此问题的正确解决方案:
此解决方案不是盲目地捕获所有异常,而是解决了问题的根源:在用于初始化对话框的活动已经完成时尝试对话框 . 使用运行KitKat的Nexus 4,但应该适用于所有版本的Android .
我同意'Damjan'的意见 .
如果你使用很多对话框,应该关闭onDestroy()或onStop()中的所有对话框 .
那么你或许可以减少'java.lang.IllegalArgumentException: View not attached to window manager'发生异常的频率 .
但是很少超过......
为了使它更清晰,你可以阻止在onDestroy调用后显示任何对话框 .
我不清楚 .
祝好运!
用这个 .
我有同样的问题,你可以通过以下方式解决:
我认为你的代码是正确的,不同于其他建议的答案 . onPostExecute将在UI线程上运行 . 这就是AsyncTask的重点 - 您不必担心调用runOnUiThread或处理处理程序 . 此外,根据文档,可以从任何线程安全地调用dismiss()(不确定它们是否为异常) .
也许这是一个计时问题,在不再显示活动后调用了dialog.dismiss()?
如果您注释掉setOnCancelListener然后在后台任务运行时退出活动,那么测试会发生什么?然后你的onPostExecute将尝试解除已经被解雇的对话框 . 如果应用程序崩溃,您可以在解除对话之前检查对话框是否打开 .
我遇到了完全相同的问题,所以我将在代码中尝试一下 .
亚历克斯,
我可能在这里错了,但我怀疑多个手机“野外”有一个错误导致他们在标记为静态的应用程序上切换方向 . 这在我的个人手机和我们小组使用的许多测试手机(包括机器人,n1,g1,英雄)上发生了很多 . 通常,标记为静态定向(可能是垂直方向)的应用程序将使用水平方向将其自身展开一两秒,然后立即进行转回来 . 最终结果是,即使您不希望您的应用切换方向,您也必须做好准备 . 我不知道在什么条件下可以重现这种行为,我不知道它是否特定于Android版本 . 我所知道的是,我已经看到它发生了很多次:(
我建议使用提供的解决方案in the link you posted建议覆盖Activity onCreateDialog方法并让Android OS管理Dialogs的生命周期 . 它看起来像我,即使你不相信有一种万无一失的方式适用于市场上所有现有的Android手机 .
大多数时候对我有用的是验证活动是否没有完成 .
刚刚遇到同样的问题 . 修复API级别13或更高级别 .
来自Android文档:
所以我改变了我的清单:
现在它工作正常 . 当我旋转手机时,活动不会重新创建,进度对话框和视图保持不变 . 对我来说没有错误 .
首先,在尝试关闭对话框时进行错误处理 .
如果这不能解决,那么在onStop()活动方法中解除它 .
使用按钮从服务器同步列表时遇到了同样的问题:1)我单击按钮2)从服务器下载列表时显示进度对话框3)我将设备转到另一个方向4)java.lang .IllegalArgumentException:在progress.dismiss()期间,在AsyncTask的postExecute()上没有附加到窗口管理器的视图 .
当我尝试修复时,我认为即使问题没有发生,我的列表也没有显示所有项目 .
我认为我想要的是AsyncTask在活动beign销毁之前完成(并关闭对话框),所以我将asynctask对象作为属性并覆盖了onDestroy()方法 .
如果asynctask需要花费很多时间,用户可能会觉得设备很慢,但我认为这是他在进度对话框出现时尝试更改设备方向所付出的代价 . 即使需要一些时间,应用程序也不会崩溃 .
下面的代码适合你,它对我很有用:
如果您从后台服务调用它,请不要全局定义您的视图 .