main

square/leakcanary

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

ToastEventListener.kt

TLDR

This file, ToastEventListener.kt, is part of the LeakCanary library. It defines an event listener object that handles different types of events and shows a toast message accordingly.

Methods

showToastBlocking

This private method is called when a DumpingHeap event occurs. It shows a blocking toast message on the main thread using the current activity. The toast displays a layout defined in the leak_canary_heap_dump_toast.xml file and includes an animated icon.

Classes

There are no classes defined in this file.

package leakcanary

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.Toast
import com.squareup.leakcanary.core.R
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit.SECONDS
import leakcanary.EventListener.Event
import leakcanary.EventListener.Event.DumpingHeap
import leakcanary.EventListener.Event.HeapDumpFailed
import leakcanary.EventListener.Event.HeapDump
import leakcanary.internal.InternalLeakCanary
import leakcanary.internal.friendly.mainHandler

object ToastEventListener : EventListener {

  // Only accessed from the main thread
  private var toastCurrentlyShown: Toast? = null

  override fun onEvent(event: Event) {
    when (event) {
      is DumpingHeap -> {
        showToastBlocking()
      }
      is HeapDump, is HeapDumpFailed -> {
        mainHandler.post {
          toastCurrentlyShown?.cancel()
          toastCurrentlyShown = null
        }
      }
      else -> {}
    }
  }

  @Suppress("DEPRECATION")
  private fun showToastBlocking() {
    val appContext = InternalLeakCanary.application
    val waitingForToast = CountDownLatch(1)
    mainHandler.post(Runnable {
      val resumedActivity = InternalLeakCanary.resumedActivity
      if (resumedActivity == null || toastCurrentlyShown != null) {
        waitingForToast.countDown()
        return@Runnable
      }
      val toast = Toast(resumedActivity)
      // Resources from application context: https://github.com/square/leakcanary/issues/2023
      val iconSize = appContext.resources.getDimensionPixelSize(
        R.dimen.leak_canary_toast_icon_size
      )
      toast.setGravity(Gravity.CENTER_VERTICAL, 0, -iconSize)
      toast.duration = Toast.LENGTH_LONG
      // Need an activity context because StrictMode added new stupid checks:
      // https://github.com/square/leakcanary/issues/2153
      val inflater = LayoutInflater.from(resumedActivity)
      toast.view = inflater.inflate(R.layout.leak_canary_heap_dump_toast, null)
      toast.show()

      val toastIcon = toast.view!!.findViewById<View>(R.id.leak_canary_toast_icon)
      toastIcon.translationY = -iconSize.toFloat()
      toastIcon
        .animate()
        .translationY(0f)
        .setListener(object : AnimatorListenerAdapter() {
          override fun onAnimationEnd(animation: Animator) {
            toastCurrentlyShown = toast
            waitingForToast.countDown()
          }
        })
    })
    waitingForToast.await(5, SECONDS)
  }
}