xref: /aosp_15_r20/external/leakcanary2/leakcanary-android-core/src/main/java/leakcanary/internal/activity/db/Io.kt (revision d9e8da70d8c9df9a41d7848ae506fb3115cae6e6)

<lambda>null1 package leakcanary.internal.activity.db
2 
3 import android.view.View
4 import leakcanary.internal.activity.db.Io.OnIo
5 import leakcanary.internal.navigation.onScreenExiting
6 import leakcanary.internal.friendly.checkMainThread
7 import leakcanary.internal.friendly.mainHandler
8 import java.util.concurrent.Executors
9 
10 internal object Io {
11 
12   private val serialExecutor =
13     Executors.newSingleThreadExecutor { runnable -> Thread(runnable, "LeakCanary-Activity-DB") }
14 
15   fun interface OnIo {
16     fun updateUi(updateUi: View.() -> Unit)
17   }
18 
19   private class IoContext : OnIo {
20     var updateUi: (View.() -> Unit)? = null
21 
22     override fun updateUi(updateUi: View.() -> Unit) {
23       this.updateUi = updateUi
24     }
25   }
26 
27   fun execute(block: () -> Unit) {
28     serialExecutor.execute(block)
29   }
30 
31   fun execute(
32     view: View,
33     block: OnIo.() -> Unit
34   ) {
35     checkMainThread()
36     val viewWrapper: VolatileObjectRef<View> = VolatileObjectRef(view)
37     view.onScreenExiting {
38       viewWrapper.element = null
39     }
40     serialExecutor.execute backgroundExecute@{
41       if (viewWrapper.element == null) {
42         return@backgroundExecute
43       }
44       val context = IoContext()
45       block(context)
46       val updateUi = context.updateUi
47       if (viewWrapper.element != null && updateUi != null) {
48         mainHandler.post mainThreadPost@{
49           val attachedView = viewWrapper.element ?: return@mainThreadPost
50           updateUi(attachedView)
51         }
52       }
53     }
54   }
55 
56   /**
57    * Similar to kotlin.jvm.internal.Ref.ObjectRef but volatile
58    */
59   private class VolatileObjectRef<T>(
60     @Volatile
61     var element: T? = null
62   )
63 }
64 
executeOnIonull65 internal fun View.executeOnIo(block: OnIo.() -> Unit) {
66   Io.execute(this, block)
67 }
68