我有一个启动AsyncTask的活动,并显示操作持续时间的进度对话框.声明活动不会通过旋转或键盘滑动重新创建.
<activity android:name=".MyActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation"
>
<intent-filter>
</intent-filter>
</activity>
Run Code Online (Sandbox Code Playgroud)
任务完成后,我会忽略对话框,但在某些手机上(框架: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)
Run Code Online (Sandbox Code Playgroud)
我的代码是:
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();
Run Code Online (Sandbox Code Playgroud)
从我已阅读(http://bend-ing.blogspot.com/2008/11/properly-handle-progress-dialog-in.html)和Android的源看到的,它看起来像唯一可能的情况下,以获取例外是活动被销毁的时候.但正如我所提到的,我禁止基本活动的活动娱乐.
所以任何建议都非常感谢.
Dam*_*jan 226
当我从onPostExecute方法中解除对话并完成活动时,我也有时会收到此错误.我猜有时活动会在对话成功解散之前完成.
简单而有效的解决方案对我有用
@Override
protected void onPostExecute(MyResult result) {
try {
if ((this.mDialog != null) && this.mDialog.isShowing()) {
this.mDialog.dismiss();
}
} catch (final IllegalArgumentException e) {
// Handle or log or ignore
} catch (final Exception e) {
// Handle or log or ignore
} finally {
this.mDialog = null;
}
}
Run Code Online (Sandbox Code Playgroud)
Ivo*_*nov 12
这是我的"防弹"解决方案,它汇集了我在这个主题上找到的所有好答案(感谢@Damjan和@Kachi).只有在所有其他检测方法都没有成功的情况下才会吞下异常.在我的情况下,我需要自动关闭对话框,这是保护应用程序免于崩溃的唯一方法.我希望它会对你有所帮助!如果您有备注或更好的解决方案,请投票并留下评论.谢谢!
public void dismissWithCheck(Dialog dialog) {
if (dialog != null) {
if (dialog.isShowing()) {
//get the Context object that was used to great the dialog
Context context = ((ContextWrapper) dialog.getContext()).getBaseContext();
// if the Context used here was an activity AND it hasn't been finished or destroyed
// then dismiss it
if (context instanceof Activity) {
// Api >=17
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (!((Activity) context).isFinishing() && !((Activity) context).isDestroyed()) {
dismissWithTryCatch(dialog);
}
} else {
// Api < 17. Unfortunately cannot check for isDestroyed()
if (!((Activity) context).isFinishing()) {
dismissWithTryCatch(dialog);
}
}
} else
// if the Context used wasn't an Activity, then dismiss it too
dismissWithTryCatch(dialog);
}
dialog = null;
}
}
public void dismissWithTryCatch(Dialog dialog) {
try {
dialog.dismiss();
} catch (final IllegalArgumentException e) {
// Do nothing.
} catch (final Exception e) {
// Do nothing.
} finally {
dialog = null;
}
}
Run Code Online (Sandbox Code Playgroud)
Pau*_*ega 11
我可能有一个解决方法.
有同样的问题,我正在加载很多项目(通过文件系统)到一个ListView通过AsyncTask.如果onPreExecute()激活a ProgressDialog,然后两者onPostExecute()和onCancelled()(当任务被明确取消时调用AsyncTask.cancel())通过关闭它.cancel().
得到相同的"java.lang.IllegalArgumentException:视图没有附加到窗口管理器"错误当我在onCancelled()方法中杀死对话框AsyncTask(我在优秀的Shelves应用程序中看到了这一点).
解决方法是创建一个AsyncTask包含以下内容的公共字段ProgressDialog:
public ProgressDialog mDialog;
Run Code Online (Sandbox Code Playgroud)
然后,onDestroy()当我取消我的时候AsyncTask,我也可以通过以下方式杀死相关的对话框:
AsyncTask.mDialog.cancel();
Run Code Online (Sandbox Code Playgroud)
呼叫AsyncTask.cancel()DOES触发onCancelled()的AsyncTask,但由于某些原因通过该方法被调用的时候,查看已经被销毁,因此撤销对话框失败.
以下是解决此问题的正确解决方案:
public void hideProgress() {
if(mProgressDialog != null) {
if(mProgressDialog.isShowing()) { //check if dialog is showing.
//get the Context object that was used to great the dialog
Context context = ((ContextWrapper)mProgressDialog.getContext()).getBaseContext();
//if the Context used here was an activity AND it hasn't been finished or destroyed
//then dismiss it
if(context instanceof Activity) {
if(!((Activity)context).isFinishing() && !((Activity)context).isDestroyed())
mProgressDialog.dismiss();
} else //if the Context used wasnt an Activity, then dismiss it too
mProgressDialog.dismiss();
}
mProgressDialog = null;
}
}
Run Code Online (Sandbox Code Playgroud)
此解决方案不是盲目地捕获所有异常,而是解决了问题的根源:在用于初始化对话框的活动已经完成时尝试对话框.使用运行KitKat的Nexus 4,但应该适用于所有版本的Android.
我同意'Damjan'的观点.
如果你使用很多对话框,应该关闭onDestroy()或onStop()中的所有对话框.
那么你可以减少频率'java.lang.IllegalArgumentException:View not attached to window manager'异常发生.
@Override
protected void onDestroy() {
Log.d(TAG, "called onDestroy");
mDialog.dismiss();
super.onDestroy();
}
Run Code Online (Sandbox Code Playgroud)
但是
,为了使它更清晰,你可以防止在onDestroy调用后显示任何对话框.
我不使用如下.但很清楚.
private boolean mIsDestroyed = false;
private void showDialog() {
closeDialog();
if (mIsDestroyed) {
Log.d(TAG, "called onDestroy() already.");
return;
}
mDialog = new AlertDialog(this)
.setTitle("title")
.setMessage("This is DialogTest")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.create();
mDialog.show();
}
private void closeDialog() {
if (mDialog != null) {
mDialog.dismiss();
}
}
@Override
protected void onDestroy() {
Log.d(TAG, "called onDestroy");
mIsDestroyed = true;
closeDialog();
super.onDestroy();
}
Run Code Online (Sandbox Code Playgroud)
祝好运!
我认为您的代码是正确的,与建议的其他答案不同。onPostExecute 将在 UI 线程上运行。这就是 AsyncTask 的全部要点 - 您不必担心调用 runOnUiThread 或处理处理程序。此外,根据文档,可以从任何线程安全地调用dismiss()(不确定他们是否将此作为例外)。
也许这是一个计时问题,在活动不再显示后调用dialog.dismiss()?
如果您注释掉 setOnCancelListener 然后在后台任务运行时退出 Activity,测试一下会发生什么?然后你的 onPostExecute 将尝试关闭已经关闭的对话框。如果应用程序崩溃,您可以在关闭对话框之前检查对话框是否打开。
我遇到了完全相同的问题,所以我将在代码中尝试一下。
| 归档时间: |
|
| 查看次数: |
100741 次 |
| 最近记录: |