FD泄露导致 leaked window 导致App Crash

关键字:com.sec.android.widgetapp.ap.hero.cmaweather

 

1. 无 Error 9 dup channel fd -2147483647.

 

2. 有 Error 9 dup channel fd -2147483647. 关键字( dup channel fd )

 

 

关键字: leaked window

 

 

 

01-19 01:22:59.773 E/WindowManager(31106): Activity com.android.settings.bluetooth.BluetoothScanDialog has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{41b3e5f8 V.E..... R......D 0,0-480,447} that was originally added here

01-19 01:22:59.773 E/WindowManager(31106): android.view.WindowLeaked: Activity com.android.settings.bluetooth.BluetoothScanDialog has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{41b3e5f8 V.E..... R......D 0,0-480,447} that was originally added here

 

android.view.WindowLeaked:已经解决

解决:好多人都说这个是内存泄漏  我自己也弄了好久 终于找到了原因 哈哈 其实不是什么内存泄漏

原因是 activity 和dialog同时显示 要先dialog.dismiss() 后activity.finish() 如果直接finish() 会出错 但不影响功能。

 

该错误是由于在Activity中创建并显示了Alertdialog,但并未使用Activity提供的showDialog()方法,因此导致在Activity被结束后,Alertdialog所引用的context为空。解决办法为,

1, 将dialog采用oncreateDialog的方式创建,交由系统维护。

2, 在onDestroy()方法中将该alertdialog dismiss掉。

 

其意思大概就是:窗体已经关闭了但是dialog仍然在显示,Activity has leaked window(activity渗透出窗体),大概就是这个意思。

那么就要在activity finish()之前将dialog dismiss()掉。

我的做法就是重写本activity的onDestroy()方法,在此方法中将dialog清除

/**

     * 此方法必须重写,以决绝退出activity时 dialog未dismiss而报错的bug

     */

    @Override

    protected void onDestroy() {

        // TODO Auto-generated method stub

        try{

            myDialog.dismiss();

        }catch (Exception e) {

            System.out.println("myDialog取消,失败!");

            // TODO: handle exception

        }

        super.onDestroy();

    }

 

 

//JBP_PROD/BAFFIN_Q/GT-I9168_CHN_ZM/android/frameworks/base/services/java/com/android/server/BluetoothManagerService.java

Looper.loop() android线程中的消息循环

Looper用于封装了android线程中的消息循环,默认情况下一个线程是不存在消息循环(message loop)的,需要调用Looper.prepare()来给线程创建一个消息循环,调用Looper.loop()来使消息循环起作用,从消息队列里取消息,处理消息。

 

注:写在Looper.loop()之后的代码不会被立即执行,当调用后mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。

 

每创建一个线程,他会占用3个FD, 如多线程不释放,那么压力测试的时候就会不断的占用FD, 而每个进程的FD数量是有限的,如果占用数量达到最大值,再申请的话就会出现leaked window异常。

最终解决

 

 

测试方法:

 

找最大的线程号,点击蓝牙图标,看弹框时时Thread后的数字会不会变大

 

 

参考资料:

Android -- Looper.prepare()和Looper.loop() —深入版

posted @ 2015-09-11 14:28  carlo-z  阅读(1433)  评论(0编辑  收藏  举报