问题描述

一个老项目,网络请求时会弹出loading,loading的技术实现是用Dialog实现的。频繁展示loading的时候,偶现DecorView not attached to window manager问题。
问题产生的调用链路是:loading显示->网络请求->异步callback回调->loading隐藏。
出现问题的时机是在异步callback回调->loading隐藏的时候。
异常堆栈如下:

java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{422f603 V.E..... R.....I. 0,0-0,0} not attached to window manager
        at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:417)
        at android.view.WindowManagerGlobal.updateViewLayout(WindowManagerGlobal.java:316)
        at android.view.WindowManagerImpl.updateViewLayout(WindowManagerImpl.java:91)
        at android.app.Dialog.onWindowAttributesChanged(Dialog.java:709)
        at android.view.Window.dispatchWindowAttributesChanged(Window.java:836)
        at com.android.internal.policy.impl.PhoneWindow.dispatchWindowAttributesChanged(PhoneWindow.java:4170)
        at android.view.Window.setGravity(Window.java:694)
        at com.xx.ui.UMBaseActivity.showLoadProgress(UMBaseActivity.java:407)
        at com.xx.ui.UMBaseActivity.showLoadProgress(UMBaseActivity.java:429)
        at com.xx.health.ui.activity.PurchaseSelectFoodActivity.requestFridgeFood(PurchaseSelectFoodActivity.java:430)
        at com.xx.health.ui.activity.PurchaseSelectFoodActivity.access$300(PurchaseSelectFoodActivity.java:44)
        at com.xx.health.ui.activity.PurchaseSelectFoodActivity$1.loadFoodSuccess(PurchaseSelectFoodActivity.java:97)
        at com.xx.health.presenter.UmTtlFoodListRecipePresenter$1.onSuccess(UmTtlFoodListRecipePresenter.java:87)
        at com.xx.health.presenter.UmTtlFoodListRecipePresenter$2$2.run(UmTtlFoodListRecipePresenter.java:180)
        at android.os.Handler.handleCallback(Handler.java:815)
        at android.os.Handler.dispatchMessage(Handler.java:104)
        at android.os.Looper.loop(Looper.java:194)
        at android.app.ActivityThread.main(ActivityThread.java:5637)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

问题分析

  1. 之前显示的对话框没有关闭,
  2. 上下文已经失效,存在窗口泄露问题

问题解决

在异步回调里做UI操作之前
隐藏dialog之前判断dialog是否处于显示状态

progressDialog.isShowing()

判断activity是否正常、页面是否销毁

   if (null == activity || activity.isDestroyed() || activity.isFinishing()) {
          LogUtil.instance().logE(TAG, "数据请求成功, 但activity异常 , activity为null了");
          return;
   }

当然以防万一,做好完整的判断更好一点

  1. progressDialog 判空
  2. progressDialog 是否展示
  3. context判空
  4. activity是否销毁
if (progressDialog != null) {
       if (progressDialog.isShowing()){
           Context context = ((ContextWrapper)progressDialog.getContext()).getBaseContext();
       if(context instanceof Activity) {
           if(!((Activity)context).isFinishing() && !((Activity)context).isDestroyed())
                  progressDialog.dismiss();
           } else {
                  progressDialog.dismiss();
           }
        }
       progressDialog = null;
}

更多推荐