main

square/leakcanary

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

CurrentActivityProvider.kt

TLDR

This file provides a CurrentActivityProvider class that allows retrieving the current activity in an application. It also includes an ActivityProviderCallbacks class that implements the ActivityLifecycleCallbacks interface.

Classes

CurrentActivityProvider

The CurrentActivityProvider class is responsible for providing access to the current activity in the application. It is annotated with @ActivityRetainedScoped and uses the @EntryPoint annotation to provide an entry point for the activity component. It contains the following methods:

  • withActivity(block: Activity.() -> T): T: This method takes a block of code and executes it with the current activity as the receiver. It ensures that the block is executed on the main thread and throws an exception if called after the activity is finished.

  • companion object: This companion object contains two methods:

    • onActivityCreated(activity: Activity): Sets the current activity to the given activity.
    • onActivityDestroyed(activity: Activity): Resets the current activity if it matches the given activity.

ActivityProviderCallbacks

The ActivityProviderCallbacks class implements the ActivityLifecycleCallbacks interface. It is used to intercept and handle activity lifecycle events. It includes empty implementations for all lifecycle methods except for onActivityCreated and onActivityDestroyed, which call the corresponding methods in CurrentActivityProvider to update the current activity.

package org.leakcanary.util

import android.app.Activity
import android.app.Application.ActivityLifecycleCallbacks
import android.os.Bundle
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.scopes.ActivityRetainedScoped
import dagger.hilt.internal.GeneratedComponentManagerHolder
import javax.inject.Inject

@EntryPoint
@InstallIn(ActivityComponent::class)
interface ActivityProviderEntryPoint {
  val activityProvider: CurrentActivityProvider
}

@ActivityRetainedScoped
class CurrentActivityProvider @Inject constructor() {

  private var currentActivity: Activity? = null

  fun <T> withActivity(block: Activity.() -> T): T {
    checkMainThread()
    val activity = currentActivity
    check(activity != null) {
      "Don't call this after the activity is finished!"
    }
    return activity.block()
  }

  companion object {
    private fun Activity.withProvider(
      block: CurrentActivityProvider.() -> Unit
    ) {
      if (this is GeneratedComponentManagerHolder) {
        val entryPoint: ActivityProviderEntryPoint =
          EntryPointAccessors.fromActivity(this)
        val provider = entryPoint.activityProvider
        provider.block()
      }
    }

    fun onActivityCreated(activity: Activity) {
      activity.withProvider {
        currentActivity = activity
      }
    }

    fun onActivityDestroyed(activity: Activity) {
      activity.withProvider {
        if (currentActivity === activity) {
          currentActivity = null
        }
      }
    }
  }
}

class ActivityProviderCallbacks : ActivityLifecycleCallbacks {

  override fun onActivityCreated(
    activity: Activity,
    savedInstanceState: Bundle?
  ) {
    CurrentActivityProvider.onActivityCreated(activity)
  }

  override fun onActivityDestroyed(activity: Activity) {
    CurrentActivityProvider.onActivityDestroyed(activity)
  }

  override fun onActivityStarted(activity: Activity) = Unit

  override fun onActivityResumed(activity: Activity) = Unit

  override fun onActivityPaused(activity: Activity) = Unit

  override fun onActivityStopped(activity: Activity) = Unit

  override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = Unit
}