I started using LeakCanary in my app. Based on various sources, I found that with this dependency:
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'
LeakCanary watches the following components by default: Activities, Fragments (both androidx.fragment.app.Fragment and android.app.Fragment), ViewModels, Services, Broadcast Receivers (especially dynamically registered ones), and View Roots.
Now, I want to log memory leaks detected in any of these components. So I wrote the following code:
private void setLeakCanaryData() {
if (BuildConfig.DEBUG) {
LeakCanary.Config oldConfig = LeakCanary.getConfig();
List<EventListener> newEventListeners = getEventListeners(oldConfig);
LeakCanary.Config newConfig = new LeakCanary.Config(
oldConfig.getDumpHeap(),
oldConfig.getDumpHeapWhenDebugging(),
oldConfig.getRetainedVisibleThreshold(),
oldConfig.getReferenceMatchers(),
oldConfig.getObjectInspectors(),
oldConfig.getOnHeapAnalyzedListener(),
oldConfig.getMetadataExtractor(),
oldConfig.getComputeRetainedHeapSize(),
oldConfig.getMaxStoredHeapDumps(),
oldConfig.getRequestWriteExternalStoragePermission(),
oldConfig.getLeakingObjectFinder(),
oldConfig.getHeapDumper(),
newEventListeners,
oldConfig.getShowNotifications(),
oldConfig.getUseExperimentalLeakFinders()
);
LeakCanary.setConfig(newConfig);
}
}
private static @NonNull List<EventListener> getEventListeners(LeakCanary.Config oldConfig) {
List<EventListener> newEventListeners = new ArrayList<>(oldConfig.getEventListeners());
newEventListeners.add(event -> {
if (event instanceof EventListener.Event.HeapAnalysisDone) {
HeapAnalysis analysis = ((EventListener.Event.HeapAnalysisDone<?>) event).getHeapAnalysis();
if (analysis instanceof HeapAnalysisSuccess) {
HeapAnalysisSuccess success = (HeapAnalysisSuccess) analysis;
for (ApplicationLeak leak : success.getApplicationLeaks()) {
sendLogInfo("Application Leak: " + leak.toString());
}
for (LibraryLeak leak : success.getLibraryLeaks()) {
sendLogInfo("Library Leak: " + leak.toString());
}
} else if (analysis instanceof HeapAnalysisFailure) {
HeapAnalysisFailure failure = (HeapAnalysisFailure) analysis;
sendLogInfo("Heap analysis failed: " + failure.getException().getMessage());
}
}
});
return newEventListeners;
}
My questions are:
Is this the correct and recommended way to log memory leaks using
LeakCanary?Is there any cleaner or more efficient method to attach event listeners in Java?
Any help or suggestions are appreciated. Thank you!