2016-05-10 85 views
0

我从泄漏金丝雀下面的堆栈跟踪与我不知道我有多么的活动是越来越泄露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(); 
    } 
+0

如果您可以发布一些相关的活动代码将会很有帮助。它看起来像ReceiverDispathcer持有对Activity上下文的引用。 – starkej2

+0

ReceiverDispatcher持有引用的原因是什么? –

+0

如果没有看到一些代码,我不能确切地告诉你什么是错误的......如果在Activity已经被销毁/重新创建后,ReceiverDispatcher对象持有对Activity上下文的引用,就可能发生这种情况。 – starkej2

回答

1

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

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

+0

真棒,谢谢..我正在阅读有关在我们使用getSystemService的地方使用应用程序上下文,并从未考虑过查看此位置。这真的有帮助 –

+0

我尝试chaning到getSystemService(Context.CONNECTIVITY_SERVICE)中的应用程序上下文,仍然泄漏 –

+0

因此,您不再使用NetworkMonitor中的任何活动上下文? – starkej2