Android微信登入引起的記憶體洩漏
阿新 • • 發佈:2019-02-06
近日公司需求跟得不緊,就自己找事優化,重構,找記憶體洩漏(如有錯誤,煩請拍磚)
記憶體洩漏工具之前的寫的部落格也有介紹 記憶體洩漏檢測工具很好用,下面用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類
注意他在onActivityPaused和onActivityResumed進行了一個延時,如果短時間再次啟動 就會造成洩漏,如果registerActivityLifecycleCallbacks是有登出方法,也基本再次開啟頁面也會有記憶體洩漏。繼續看你會發現一個detach方法,也就是微信寫了釋放,但是demo和文件沒有說這個事。看到這裡你應該就明白怎麼解決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; } }
在WeChatLoginActivity中的onDestroy中呼叫IWXAPI.detach();即可
因為微信登入正常就開啟第一次然後就不會再開啟,所以這個記憶體洩漏基本不會遇到。