<lambda>null1package 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 executeOnIonull65internal fun View.executeOnIo(block: OnIo.() -> Unit) { 66 Io.execute(this, block) 67 } 68