Android微信登录引起的内存泄漏

来源:互联网 发布:js动态添加class样式 编辑:程序博客网 时间:2024/06/05 07:11

近日公司需求跟得不紧,就自己找事优化,重构,找内存泄漏(如有错误,烦请拍砖大笑)

内存泄漏工具之前的写的博客也有介绍 内存泄漏检测工具很好用,下面用LeakCanary找一个微信登录引起的内存泄漏(其实微信是有做释放操作,但是文档和demo中没有见到)

泄漏信息


图中可以看出自己应用的WeChatLoginActivity的实例没有回收掉导致的内存泄漏,再往上是WXApiImpV10中的一个内部类ActivityLifecycleCb中持有WeChatLoginActivity的实例导致的

不多说看微信SDK源码

查看createWXAPI的方法(因为WeChatLoginActivity的context是从这里传入的)

    public static IWXAPI createWXAPI(Context var0, String var1, boolean var2) {        b.e("MicroMsg.PaySdk.WXFactory", "createWXAPI, appId = " + var1 + ", checkSignature = " + var2);        return new WXApiImplV10(var0, var1, var2);    }

比较简单直接进入WXApiImplV10,继续看WXApiImplV10


构造方法保存了context,registerApp方法中创建了activitycb,而且我们的泄漏最终是activitycb导致,registerActivityLifecycleCallbacks这个方法我不了解,也没看过大概实现,不过一般注册都有注销,这个暂时搁置。继续看ActivityLifecycleCb类

   private static final class ActivityLifecycleCb implements ActivityLifecycleCallbacks {        private static final String TAG = "MicroMsg.SDK.WXApiImplV10.ActivityLifecycleCb";        private static final int DELAYED = 800;        private boolean isForeground;        private Handler handler;        private Context context;        private Runnable onPausedRunnable;        private Runnable onResumedRunnable;        private ActivityLifecycleCb(Context var1) {            this.isForeground = false;            this.handler = new Handler(Looper.getMainLooper());            this.onPausedRunnable = new Runnable() {                public void run() {                    if(WXApiImplV10.activityCb != null && ActivityLifecycleCb.this.isForeground) {                        Log.v("MicroMsg.SDK.WXApiImplV10.ActivityLifecycleCb", "WXStat trigger onBackground");                        StatService.trackCustomKVEvent(ActivityLifecycleCb.this.context, "onBackground_WX", (Properties)null);                        ActivityLifecycleCb.this.isForeground = false;                    }                }            };            this.onResumedRunnable = new Runnable() {                public void run() {                    if(WXApiImplV10.activityCb != null && !ActivityLifecycleCb.this.isForeground) {                        Log.v("MicroMsg.SDK.WXApiImplV10.ActivityLifecycleCb", "WXStat trigger onForeground");                        StatService.trackCustomKVEvent(ActivityLifecycleCb.this.context, "onForeground_WX", (Properties)null);                        ActivityLifecycleCb.this.isForeground = true;                    }                }            };            this.context = var1;        }        public final void onActivityCreated(Activity var1, Bundle var2) {        }        public final void onActivityDestroyed(Activity var1) {        }        public final void onActivityPaused(Activity var1) {            Log.v("MicroMsg.SDK.WXApiImplV10.ActivityLifecycleCb", var1.getComponentName().getClassName() + "  onActivityPaused");            this.handler.removeCallbacks(this.onResumedRunnable);            this.handler.postDelayed(this.onPausedRunnable, 800L);        }        public final void onActivityResumed(Activity var1) {            Log.v("MicroMsg.SDK.WXApiImplV10.ActivityLifecycleCb", var1.getComponentName().getClassName() + "  onActivityResumed");            this.handler.removeCallbacks(this.onPausedRunnable);            this.handler.postDelayed(this.onResumedRunnable, 800L);        }        public final void onActivitySaveInstanceState(Activity var1, Bundle var2) {        }        public final void onActivityStarted(Activity var1) {        }        public final void onActivityStopped(Activity var1) {        }        public final void detach() {            this.handler.removeCallbacks(this.onResumedRunnable);            this.handler.removeCallbacks(this.onPausedRunnable);            this.context = null;        }    }
注意他在onActivityPaused和onActivityResumed进行了一个延时,如果短时间再次启动  就会造成泄漏,如果registerActivityLifecycleCallbacks是有注销方法,也基本再次打开页面也会有内存泄漏。继续看你会发现一个detach方法,也就是微信写了释放,但是demo和文档没有说这个事。看到这里你应该就明白怎么解决


WeChatLoginActivity中的onDestroy中调用IWXAPI.detach();即可

因为微信登录正常就打开第一次然后就不会再打开,所以这个内存泄漏基本不会遇到。


0 0
原创粉丝点击