android查看不附加到窗口pipe理器
我有以下一些例外:
java.lang.IllegalArgumentException: View not attached to window manager at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:355) at android.view.WindowManagerImpl.updateViewLayout(WindowManagerImpl.java:191) at android.view.Window$LocalWindowManager.updateViewLayout(Window.java:428) at android.app.Dialog.onWindowAttributesChanged(Dialog.java:596) at android.view.Window.setDefaultWindowFormat(Window.java:1013) at com.android.internal.policy.impl.PhoneWindow.access$700(PhoneWindow.java:86) at com.android.internal.policy.impl.PhoneWindow$DecorView.drawableChanged(PhoneWindow.java:1951) at com.android.internal.policy.impl.PhoneWindow$DecorView.fitSystemWindows(PhoneWindow.java:1889) at android.view.ViewRoot.performTraversals(ViewRoot.java:727) at android.view.ViewRoot.handleMessage(ViewRoot.java:1633) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:123) at android.app.ActivityThread.main(ActivityThread.java:4338) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) at dalvik.system.NativeStart.main(Native Method)
我已经GOOGLE了,看到它与popup窗口和转动屏幕有关,但没有提及我的代码。
问题是:
- 有没有办法找出这个问题发生的时间?
- 除了转动屏幕,还有其他事件或行动触发这个错误?
- 我如何防止这种情况发生?
我在屏幕方向改变的地方遇到了这个问题,活动在完成进度对话框之前完成了AsyncTask。 我似乎通过将对话框设置为null onPause()
,然后在解散之前在AsyncTask中检查此解决此问题。
@Override public void onPause() { super.onPause(); if ((mDialog != null) && mDialog.isShowing()) mDialog.dismiss(); mDialog = null; }
…在我的AsyncTask中:
protected void onPreExecute() { mDialog = ProgressDialog.show(mContext, "", "Saving changes...", true); } protected void onPostExecute(Object result) { if ((mDialog != null) && mDialog.isShowing()) { mDialog.dismiss(); } }
经过与这个问题的斗争,我终于结束了这个解决方法:
/** * Dismiss {@link ProgressDialog} with check for nullability and SDK version * * @param dialog instance of {@link ProgressDialog} to dismiss */ public void dismissProgressDialog(ProgressDialog 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()) { dismissWithExceptionHandling(dialog); } } else { // Api < 17. Unfortunately cannot check for isDestroyed() if (!((Activity) context).isFinishing()) { dismissWithExceptionHandling(dialog); } } } else // if the Context used wasn't an Activity, then dismiss it too dismissWithExceptionHandling(dialog); } dialog = null; } } /** * Dismiss {@link ProgressDialog} with try catch * * @param dialog instance of {@link ProgressDialog} to dismiss */ public void dismissWithExceptionHandling(ProgressDialog dialog) { try { dialog.dismiss(); } catch (final IllegalArgumentException e) { // Do nothing. } catch (final Exception e) { // Do nothing. } finally { dialog = null; } }
有时候,如果这个问题没有更好的解决scheme,那么好的exception处理工作就会很好。
我将以下内容添加到该活动的清单中
android:configChanges="keyboardHidden|orientation|screenLayout"
如果你有一个Activity
对象,你可以使用isDestroyed()
方法:
Activity activity; // ... if (!activity.isDestroyed()) { // ... }
如果你在不同的地方使用非匿名的AsyncTask
子类,这很好。
我正在使用自定义的静态类,它使显示和隐藏对话框。 这个class级也被其他活动所使用,不仅仅是一个活动。 现在你所描述的问题也出现在我身上,我一夜之间find了解决办法。
最后我给你解决scheme!
如果你想显示或解除一个对话框,你不知道哪个活动发起对话,以触摸它,那么下面的代码是给你的..
static class CustomDialog{ public static void initDialog(){ ... //init code ... } public static void showDialog(){ ... //init code for show dialog ... } /****This is your Dismiss dialog code :D*******/ public static void dismissProgressDialog(Context context) { //Can't touch other View of other Activiy.. //http://stackoverflow.com/questions/23458162/dismiss-progress-dialog-in-another-activity-android if ( (progressdialog != null) && progressdialog.isShowing()) { //is it the same context from the caller ? Log.w("ProgressDIalog dismiss", "the dialog is from"+progressdialog.getContext()); Class caller_context= context.getClass(); Activity call_Act = (Activity)context; Class progress_context= progressdialog.getContext().getClass(); Boolean is_act= ( (progressdialog.getContext()) instanceof Activity )?true:false; Boolean is_ctw= ( (progressdialog.getContext()) instanceof ContextThemeWrapper )?true:false; if (is_ctw) { ContextThemeWrapper cthw=(ContextThemeWrapper) progressdialog.getContext(); Boolean is_same_acivity_with_Caller= ((Activity)(cthw).getBaseContext() == call_Act )?true:false; if (is_same_acivity_with_Caller){ progressdialog.dismiss(); progressdialog = null; } else { Log.e("ProgressDIalog dismiss", "the dialog is NOT from the same context! Can't touch.."+((Activity)(cthw).getBaseContext()).getClass()); progressdialog = null; } } } } }
对于问题1):
考虑到错误消息似乎并没有说你的代码的哪一行导致了麻烦,你可以通过使用断点来追踪它。 当程序到达特定的代码行时,断点暂停执行程序。 通过添加断点到关键位置,您可以确定哪一行代码导致崩溃。 例如,如果你的程序崩溃在一个setContentView()行,你可以在那里放置一个断点。 程序运行时,会在运行该行之前暂停。 如果然后恢复导致程序在到达下一个断点之前崩溃,那么您知道杀死该程序的行在两个断点之间。
如果您使用Eclipse,添加断点很容易。 右键单击代码左边的空白处,然后select“切换断点”。 然后,您需要在debugging模式下运行应用程序,该button看起来像正常运行button旁边的绿色昆虫。 当程序遇到断点时,Eclipse将切换到debugging透视图并显示它正在等待的行。 要再次启动程序,请查找“恢复”button,该button看起来像普通的“播放”,但在三angular形的左侧有一个垂直条。
您也可以使用Log.d(“我的应用程序”,“这里的一些信息告诉你日志行在哪里”)填写你的应用程序,然后在Eclipse的LogCat窗口中发布消息。 如果你找不到那个窗口,打开窗口 – >显示视图 – >其他… – > Android – > LogCat。
希望有所帮助!
根据windowManager的代码( 这里是链接),当您试图更新的视图(可能属于对话框,但不是必需的)不再附加到窗口的实际根目录时,会发生这种情况。
正如其他人所build议的那样,您应该在对话框上执行特殊操作之前检查活动的状态。
这里是相关的代码,这是问题的原因(从Android源代码复制):
public void updateViewLayout(View view, ViewGroup.LayoutParams params) { if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; view.setLayoutParams(wparams); synchronized (this) { int index = findViewLocked(view, true); ViewRootImpl root = mRoots[index]; mParams[index] = wparams; root.setLayoutParams(wparams, false); } } private int findViewLocked(View view, boolean required) { synchronized (this) { final int count = mViews != null ? mViews.length : 0; for (int i=0; i<count; i++) { if (mViews[i] == view) { return i; } } if (required) { throw new IllegalArgumentException( "View not attached to window manager"); } return -1; } }
我的问题是解决了屏幕旋转我的android应用程序,这是我的问题,现在完美的作品
另一个选项是不要启动asynchronous任务,直到通过覆盖对话框上的onAttachedToWindow()将对话框附加到窗口上,这样它总是被允许的。
或者你可以添加
protected void onPreExecute() { mDialog = ProgressDialog.show(mContext, "", "Saving changes...", true, false); }
这将使ProgressDialog
不能取消
当您在清单中声明活动时,您需要android:configChanges =“orientation”
例:
<activity android:theme="@android:style/Theme.Light.NoTitleBar" android:configChanges="orientation" android:label="traducción" android:name=".PantallaTraductorAppActivity"></activity>
为什么不尝试赶上,像这样:
protected void onPostExecute(Object result) { try { if ((mDialog != null) && mDialog.isShowing()) { mDialog.dismiss(); } } catch (Exception ex) { Log.e(TAG, ex.getMessage(), ex); } }