当前位置: 代码迷 >> Android >> 尽管使用了WeakReference,AlertDialog仍然泄漏
  详细解决方案

尽管使用了WeakReference,AlertDialog仍然泄漏

热度:92   发布时间:2023-08-04 09:50:56.0

我在处理程序中创建AlertDialog时遇到问题,因为它会导致内存泄漏或其他错误。

细节:

我有一个Activity,Thread和Handler与对活动的WeakReference。 在开始线程之前,我在活动类中创建ProgressDialog dialog 线程任务具有对MyHandler对象的引用。 当用户在我的活动中关闭dialog时,onCancelListener会调用线程的interrupt()。 我的线程安全地完成了任务,并向主活动线程发送了消息DOWNLOAD_STATE.CANCELLED。 然后我在MyHandler中使用代码MyHandler

问题:

问题是,当用户在解除alert (取消线程)并在创建新的AlertDialog之前(在MyHandler类内部)按下后退按钮。 花了大约第二秒。 当用户此时不回压时,一切正常。

它在这里泄漏(在MyHandler类内部): new AlertDialog.Builder(activity).setMessage("update cancelled").setPositiveButton("OK", null).show();

正常的情况是,当用户按下“后退”按钮时,活动被销毁(活动onBackKeyPressed的效果),但是为什么不停止AlertDialog并创建AlertDialog呢?

我的处理程序类:

static class MyHandler extends Handler {

    WeakReference<MainActivity> activityRef;
    MyHandler(MainActivity activity)
    {
        this.activityRef=new WeakReference<MainActivity>(activity);
    }

    @Override
    public void handleMessage(Message msg) {

        MainActivity activity=activityRef.get();
        if(activity==null)
            return;

        if (msg.arg1==DownloadTask.DOWNLOAD_STATE.FINISHED.ordinal())
        {
            activity.dialog.dismiss();
            Toast.makeText(activity, "updated", Toast.LENGTH_LONG).show();
        }

        else if( msg.arg1== DownloadTask.DOWNLOAD_STATE.CANCELLED.ordinal())
        {
            new AlertDialog.Builder(activity).setMessage("update cancelled").setPositiveButton("OK", null).show();
        }

        else if(msg.arg1==DownloadTask.DOWNLOAD_STATE.ERROR.ordinal())
        {

              activity.dialog.dismiss();
            new AlertDialog.Builder(activity).setMessage(activity.getString(R.string.no_connection_info)).setPositiveButton("OK", null).show();
        }

    }
}

内部线程的可运行状态:

if(Thread.interrupted()) 
        {
            Message msg=handler.obtainMessage();
            msg.arg1=DOWNLOAD_STATE.CANCELLED.ordinal();
            msg.arg2=counter;
            msg.obj=cities.length;
            handler.sendMessage(msg);

            return;
        }

错误堆栈跟踪1:

android.view.WindowLeaked: Activity com.mycompany.mooz.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@42723848 that was originally added here
        at android.view.ViewRootImpl.<init>(ViewRootImpl.java:403)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:311)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)
        at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)
        at android.view.Window$LocalWindowManager.addView(Window.java:554)
        at android.app.Dialog.show(Dialog.java:277)
        at android.support.v7.app.AlertDialog$Builder.show(AlertDialog.java:902)
        at com.mycompany.mooz.MainActivity$MyHandler.handleMessage(MainActivity.java:55)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4921)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
        at dalvik.system.NativeStart.main(Native Method)

错误堆栈跟踪2:

android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@427329e0 is not valid; is your activity running?
        at android.view.ViewRootImpl.setView(ViewRootImpl.java:700)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:345)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)
        at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)
        at android.view.Window$LocalWindowManager.addView(Window.java:554)
        at android.app.Dialog.show(Dialog.java:277)
        at android.support.v7.app.AlertDialog$Builder.show(AlertDialog.java:902)
        at com.mycompany.mooz.MainActivity`enter code here`$MyHandler.handleMessage(MainActivity.java:55)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4921)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
        at dalvik.system.NativeStart.main(Native Method)

活动com.mycompany.mooz.MainActivity泄漏了最初在此处添加的窗口com.android.internal.policy.impl.PhoneWindow$DecorView@42723848

通常在“ Activity被暂停且对话框仍在屏幕上时发生。 保留对Dialog的引用,如果引用不为null并且对话框isShowing则在onPause调用dismiss

  if (mDialog != null && mDialog.isShowing()) {
        mDialog.dismiss();
  }

android.view.WindowManager $ BadTokenException:无法添加窗口-令牌android.os.BinderProxy@427329e0无效; 您的活动正在进行吗?

当您在“活动”暂停时尝试显示对话框时,通常会发生这种情况。 为了避免检查isFinishing标志

  if (activity != null && !activity.isFinishing()) {
      // show dialog
  }
  相关解决方案