Skip to content

Commit

Permalink
watch leaking support library fragments and their views
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreasBoehm committed Nov 5, 2019
1 parent 1f6c971 commit 9a0961d
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 0 deletions.
1 change: 1 addition & 0 deletions build.gradle
Expand Up @@ -34,6 +34,7 @@ buildscript {
mockito_kotlin: 'com.nhaarman:mockito-kotlin-kt1.1:1.5.0',
okio: 'com.squareup.okio:okio:2.2.2',
robolectric : 'org.robolectric:robolectric:4.0-alpha-3',
android_support: 'com.android.support:support-v4:28.0.0'
]
repositories {
google()
Expand Down
25 changes: 25 additions & 0 deletions leakcanary-object-watcher-android-support-fragments/build.gradle
@@ -0,0 +1,25 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

dependencies {
api project(':leakcanary-object-watcher-android')

implementation deps.kotlin.stdlib
// Optional dependency
compileOnly deps.android_support
}

android {
compileSdkVersion versions.compileSdk
defaultConfig {
minSdkVersion versions.minSdk
consumerProguardFiles 'consumer-proguard-rules.pro'
}
lintOptions {
disable 'GoogleAppIndexingWarning'
error 'ObsoleteSdkInt'
check 'Interoperability'
}
}

apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
@@ -0,0 +1,2 @@
# AndroidSupportFragmentDestroyWatcher is loaded via reflection
-keep class leakcanary.internal.AndroidSupportFragmentDestroyWatcher { *; }
@@ -0,0 +1,3 @@
POM_ARTIFACT_ID=leakcanary-object-watcher-android-support-fragments
POM_NAME=LeakCanary Object Watcher for Android extension: Android support library fragments support
POM_PACKAGING=aar
@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.squareup.leakcanary.fragments.android_support" />
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2018 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package leakcanary.internal

import android.app.Activity
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentActivity
import android.support.v4.app.FragmentManager
import leakcanary.AppWatcher.Config
import leakcanary.ObjectWatcher

internal class AndroidSupportFragmentDestroyWatcher(
private val objectWatcher: ObjectWatcher,
private val configProvider: () -> Config
) : (Activity) -> Unit {

private val fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() {

override fun onFragmentViewDestroyed(
fm: FragmentManager,
fragment: Fragment
) {
val view = fragment.view
if (view != null && configProvider().watchFragmentViews) {
objectWatcher.watch(view)
}
}

override fun onFragmentDestroyed(
fm: FragmentManager,
fragment: Fragment
) {
if (configProvider().watchFragments) {
objectWatcher.watch(fragment)
}
}
}

override fun invoke(activity: Activity) {
if (activity is FragmentActivity) {
val supportFragmentManager = activity.supportFragmentManager
supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true)
}
}
}
Expand Up @@ -33,6 +33,10 @@ internal object FragmentDestroyWatcher {
private const val ANDROIDX_FRAGMENT_DESTROY_WATCHER_CLASS_NAME =
"leakcanary.internal.AndroidXFragmentDestroyWatcher"

private const val ANDROID_SUPPORT_FRAGMENT_CLASS_NAME = "android.support.v4.app.Fragment"
private const val ANDROID_SUPPORT_FRAGMENT_DESTROY_WATCHER_CLASS_NAME =
"leakcanary.internal.AndroidSupportFragmentDestroyWatcher"

fun install(
application: Application,
objectWatcher: ObjectWatcher,
Expand All @@ -57,6 +61,17 @@ internal object FragmentDestroyWatcher {
)
}

if (classAvailable(ANDROID_SUPPORT_FRAGMENT_CLASS_NAME) &&
classAvailable(ANDROID_SUPPORT_FRAGMENT_DESTROY_WATCHER_CLASS_NAME)
) {
val watcherConstructor = Class.forName(ANDROID_SUPPORT_FRAGMENT_DESTROY_WATCHER_CLASS_NAME)
.getDeclaredConstructor(ObjectWatcher::class.java, Function0::class.java)
@kotlin.Suppress("UNCHECKED_CAST")
fragmentDestroyWatchers.add(
watcherConstructor.newInstance(objectWatcher, configProvider) as (Activity) -> Unit
)
}

if (fragmentDestroyWatchers.size == 0) {
return
}
Expand Down
1 change: 1 addition & 0 deletions settings.gradle
Expand Up @@ -6,6 +6,7 @@ include ':leakcanary-android-sample'
include ':leakcanary-object-watcher'
include ':leakcanary-object-watcher-android'
include ':leakcanary-object-watcher-android-androidx'
include ':leakcanary-object-watcher-android-support-fragments'
include ':shark'
include ':shark-android'
include ':shark-cli'
Expand Down

0 comments on commit 9a0961d

Please sign in to comment.