main

square/leakcanary

Last updated at: 29/12/2023 09:38

AndroidXFragmentDestroyWatcher.kt

TLDR

This file contains the AndroidXFragmentDestroyWatcher class, which is responsible for watching the lifecycle of AndroidX fragments and detecting possible memory leaks. It installs ViewModelClearedWatcher on each created fragment to ensure that any references to its views are properly cleared to prevent leaks. It also listens for Fragment#onDestroyView() and Fragment#onDestroy() callbacks to expect weakly reachable fragments and views, respectively.

Classes

AndroidXFragmentDestroyWatcher

This class implements the (Activity) -> Unit interface and is responsible for watching the lifecycle of AndroidX fragments. It installs ViewModelClearedWatcher on each created fragment to ensure that any references to its views are properly cleared to prevent memory leaks. It also listens for Fragment#onDestroyView() and Fragment#onDestroy() callbacks to expect weakly reachable fragments and views, respectively.

The class has the following properties and methods:

  • reachabilityWatcher: An instance of the ReachabilityWatcher class used to detect memory leaks.
  • fragmentLifecycleCallbacks: An anonymous inner class that extends FragmentManager.FragmentLifecycleCallbacks and overrides certain methods to watch for fragment lifecycle events.

The class has a single method, invoke(activity: Activity), which takes an Activity as a parameter. If the activity is an instance of FragmentActivity, it registers the fragmentLifecycleCallbacks to listen for fragment lifecycle events in the activity's SupportFragmentManager. Additionally, it installs ViewModelClearedWatcher on the activity to watch for ViewModel clearing.

/*
 * 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.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import leakcanary.ReachabilityWatcher

internal class AndroidXFragmentDestroyWatcher(
  private val reachabilityWatcher: ReachabilityWatcher
) : (Activity) -> Unit {

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

    override fun onFragmentCreated(
      fm: FragmentManager,
      fragment: Fragment,
      savedInstanceState: Bundle?
    ) {
      ViewModelClearedWatcher.install(fragment, reachabilityWatcher)
    }

    override fun onFragmentViewDestroyed(
      fm: FragmentManager,
      fragment: Fragment
    ) {
      val view = fragment.view
      if (view != null) {
        reachabilityWatcher.expectWeaklyReachable(
          view, "${fragment::class.java.name} received Fragment#onDestroyView() callback " +
          "(references to its views should be cleared to prevent leaks)"
        )
      }
    }

    override fun onFragmentDestroyed(
      fm: FragmentManager,
      fragment: Fragment
    ) {
      reachabilityWatcher.expectWeaklyReachable(
        fragment, "${fragment::class.java.name} received Fragment#onDestroy() callback"
      )
    }
  }

  override fun invoke(activity: Activity) {
    if (activity is FragmentActivity) {
      val supportFragmentManager = activity.supportFragmentManager
      supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true)
      ViewModelClearedWatcher.install(activity, reachabilityWatcher)
    }
  }
}