泄漏堆栈跟踪很难理解

时间:2016-05-10 20:59:44

标签: android leakcanary

我有来自泄漏金丝雀的以下堆栈跟踪,我不确定我的活动是如何泄露的

static LGCobtextHelper.mLGContext
references LGContext.mContext
references
ResourcesContextWrapperFactory$WebViewContextWrapper.mBase
references
com.*.*.activity.MyActivity.networkMonitor
references
com.*.*.NetworkMonitor.mPendingResult
references
android.app.LoadedApk$ReceiverDispatcher$Args.this$0
references
LoadedAok$ReceiverDispathcer.mContext
leaks MyActivity instance

MyActivity扩展BaseActivity,注册onResume()并取消注册onPause(),因此不确定哪个活动泄漏

NetworkMonitor.java

     public class NetworkMonitor extends BroadcastReceiver {
    private final WebSocketClient webSocketClient;
    private final ArmingHelper armingHelper;
    private final ShutdownManager shutdownManager;
    private final CameraThumbnailCache cameraThumbnailCache;
    private final CameraAccessManager cameraAccessManager;
    private final JoustLogger joustLogger;

    private Activity registeredActivity;
    private String currentNetworkName;
    private List<NetworkStatusChangeListener> networkChangeListeners;

    public interface NetworkStatusChangeListener {
        void onNetworkUp();
        void onNetworkDown();
    }

    public NetworkMonitor(WebSocketClient webSocketClient, ArmingHelper armingHelper, ShutdownManager shutdownManager, CameraThumbnailCache cameraThumbnailCache, CameraAccessManager cameraAccessManager, JoustLogger joustLogger) {
        this.webSocketClient = webSocketClient;
        this.armingHelper = armingHelper;
        this.shutdownManager = shutdownManager;
        this.cameraThumbnailCache = cameraThumbnailCache;
        this.cameraAccessManager = cameraAccessManager;
        this.joustLogger = joustLogger;
        networkChangeListeners = new ArrayList<>();
    }

    // Activities *must* call this method in onResume() in order for
    // the app to watch for network changes
    public void startListeningForNetworkChanges(Activity registeringActivity) {
        if (!(registeringActivity instanceof NetworkStatusChangeListener)) {
            throw new IllegalArgumentException("Registering Activity must implement NetworkStatusChangeListener");
        }

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        intentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        intentFilter.addAction(GlobalConstants.ANDROID_NET_WIFI_WIFI_STATE_CHANGED);
        registeringActivity.registerReceiver(this, intentFilter);
        this.registeredActivity = registeringActivity;
        registerListenerForNetworkChanges((NetworkStatusChangeListener)registeringActivity);
    }

    // Activities *must* call this method in onPause() in order to properly
    // unregister the receiver that was set in onResume()
    public void stopListeningForNetworkChanges(Activity registeringActivity) {
        registeringActivity.unregisterReceiver(this);
        unregisterListenerForNetworkChanges((NetworkStatusChangeListener)registeringActivity);
        registeredActivity = null;
    }

    // Fragments can use this method to register for Network change updates, call in onResume()
    public void registerListenerForNetworkChanges(NetworkStatusChangeListener listener) {
        networkChangeListeners.add(listener);
    }

    // Fragments need to unregister in onPause()
    public void unregisterListenerForNetworkChanges(NetworkStatusChangeListener listener) {
        networkChangeListeners.remove(listener);
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        checkNetworkConnection();
    }

    public void checkNetworkConnection() {
        if (registeredActivity != null) {
            final ConnectivityManager connectivityManager = (ConnectivityManager) registeredActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
            if (networkInfo != null && networkInfo.isConnectedOrConnecting()) {
                String newNetworkName = networkInfo.getTypeName();
                if (currentNetworkName == null || !currentNetworkName.equals(newNetworkName)) {
                    Timber.d("Network(%s) Connected", newNetworkName);
                    // Our network was down, but now it's up.  Validate the Websocket
                    currentNetworkName = newNetworkName;
                    cameraThumbnailCache.clearInternalURLPreferences();
                    webSocketClient.reopenWebsocketIfPossible();
                    cameraAccessManager.onNetworkUp();
                    if (ActivityBehaviorHelper.needsSecurityCountdown(registeredActivity)) {
                        armingHelper.startTimerIfReady();
                    }
                    for (NetworkStatusChangeListener listener : networkChangeListeners) {
                        listener.onNetworkUp();
                    }
                    joustLogger.onNetworkUp();
                }
            } else {
                Timber.w("Network Down");
                currentNetworkName = null;
                cameraAccessManager.onNetworkDown();
                joustLogger.onNetworkDown();
                shutdownManager.onNetworkDown();
                for (NetworkStatusChangeListener listener : networkChangeListeners) {
                    listener.onNetworkDown();
                }
            }
        }
    }
}


BaseActivity.java

   @Override
    protected void onResume() {
        super.onResume();
        networkMonitor.startListeningForNetworkChanges(this);
    }

    @Override
    protected void onPause() {
        networkMonitor.stopListeningForNetworkChanges(this);
        super.onPause();
    }

1 个答案:

答案 0 :(得分:1)

看起来您可能不需要在该NetworkMonitor类中持有对Activity的引用。这可能是您的内存泄漏的来源 - 活动参考可能在活动被销毁后被保留。看起来您可以将上下文作为参数传递给需要它的方法。

此外,对于这里使用Activity上下文的一些位置,例如context.getSystemService(Context.CONNECTIVITY_SERVICE),您可以使用Application上下文,并且可能完全避免需要Activity引用。