<lambda>null1 package leakcanary
2 
3 import android.app.Activity
4 import android.app.Application
5 import android.os.Bundle
6 import android.os.Looper
7 import androidx.annotation.IdRes
8 import androidx.fragment.app.Fragment
9 import androidx.fragment.app.FragmentActivity
10 import androidx.fragment.app.FragmentManager
11 import androidx.lifecycle.ViewModel
12 import androidx.lifecycle.ViewModelProvider
13 import androidx.lifecycle.ViewModelProvider.Factory
14 import androidx.lifecycle.ViewModelStoreOwner
15 import androidx.test.core.app.ApplicationProvider
16 import androidx.test.platform.app.InstrumentationRegistry
17 import androidx.test.rule.ActivityTestRule
18 import java.util.concurrent.CountDownLatch
19 import java.util.concurrent.atomic.AtomicReference
20 import kotlin.reflect.KClass
21 import leakcanary.internal.friendly.noOpDelegate
22 
23 interface HasActivityTestRule<T : Activity> {
24   val activityRule: ActivityTestRule<T>
25 
26   val activity: T
27     get() = activityRule.activity!!
28 }
29 
activityTestRulenull30 inline fun <reified T : Activity> activityTestRule(
31   initialTouchMode: Boolean = false,
32   launchActivity: Boolean = true
33 ): ActivityTestRule<T> = ActivityTestRule(
34   T::class.java, initialTouchMode, launchActivity
35 )
36 
37 fun <R> triggersOnActivityCreated(block: () -> R): R {
38   return waitForTriggered(block) { triggered ->
39     val app = ApplicationProvider.getApplicationContext<Application>()
40     app.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
41       override fun onActivityCreated(
42         activity: Activity,
43         savedInstanceState: Bundle?
44       ) {
45         app.unregisterActivityLifecycleCallbacks(this)
46         triggered()
47       }
48     })
49   }
50 }
51 
retainednull52 infix fun Any.retained(block: () -> Unit) {
53   block()
54   "" + this
55 }
56 
triggersOnActivityDestroyednull57 fun <T : FragmentActivity, R> HasActivityTestRule<T>.triggersOnActivityDestroyed(block: () -> R): R {
58   return waitForTriggered(block) { triggered ->
59     val testActivity = activity
60     testActivity.application.registerActivityLifecycleCallbacks(
61       object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
62         override fun onActivityDestroyed(activity: Activity) {
63           if (activity == testActivity) {
64             activity.application.unregisterActivityLifecycleCallbacks(this)
65             Looper.myQueue()
66               .addIdleHandler {
67                 triggered()
68                 false
69               }
70           }
71         }
72       })
73   }
74 }
75 
triggersOnFragmentCreatednull76 fun <T : FragmentActivity, R> HasActivityTestRule<T>.triggersOnFragmentCreated(block: () -> R): R {
77   return waitForTriggered(block) { triggered ->
78     val fragmentManager = activity.supportFragmentManager
79     fragmentManager.registerFragmentLifecycleCallbacks(
80       object : FragmentManager.FragmentLifecycleCallbacks() {
81         override fun onFragmentCreated(
82           fm: FragmentManager,
83           fragment: Fragment,
84           savedInstanceState: Bundle?
85         ) {
86           fragmentManager.unregisterFragmentLifecycleCallbacks(this)
87           triggered()
88         }
89       }, false
90     )
91   }
92 }
93 
triggersOnFragmentViewDestroyednull94 fun <T : FragmentActivity, R> HasActivityTestRule<T>.triggersOnFragmentViewDestroyed(block: () -> R): R {
95   return waitForTriggered(block) { triggered ->
96     val fragmentManager = activity.supportFragmentManager
97     fragmentManager.registerFragmentLifecycleCallbacks(
98       object : FragmentManager.FragmentLifecycleCallbacks() {
99         override fun onFragmentViewDestroyed(
100           fm: FragmentManager,
101           fragment: Fragment
102         ) {
103           fragmentManager.unregisterFragmentLifecycleCallbacks(this)
104           triggered()
105         }
106       }, false
107     )
108   }
109 }
110 
waitForTriggerednull111 fun <R> waitForTriggered(
112   trigger: () -> R,
113   triggerListener: (triggered: () -> Unit) -> Unit
114 ): R {
115   val latch = CountDownLatch(1)
116   triggerListener {
117     latch.countDown()
118   }
119   val result = trigger()
120   latch.await()
121   return result
122 }
123 
getOnMainSyncnull124 fun <T> getOnMainSync(block: () -> T): T {
125   val resultHolder = AtomicReference<T>()
126   val latch = CountDownLatch(1)
127   InstrumentationRegistry.getInstrumentation()
128     .runOnMainSync {
129       resultHolder.set(block())
130       latch.countDown()
131     }
132   latch.await()
133   return resultHolder.get()
134 }
135 
runOnMainSyncnull136 fun runOnMainSync(block: () -> Unit) = InstrumentationRegistry.getInstrumentation()
137   .runOnMainSync(block)
138 
139 fun <T : ViewModel> ViewModelStoreOwner.installViewModel(modelClass: KClass<T>): T =
140   ViewModelProvider(this, object : Factory {
141     override fun <T : ViewModel> create(modelClass: Class<T>): T = modelClass.newInstance()
142   }).get(modelClass.java)
143 
addFragmentNownull144 fun FragmentActivity.addFragmentNow(fragment: Fragment) {
145   supportFragmentManager
146     .beginTransaction()
147     .add(0, fragment)
148     .commitNow()
149 }
150 
FragmentActivitynull151 fun FragmentActivity.replaceWithBackStack(
152   fragment: Fragment,
153   @IdRes containerViewId: Int
154 ) {
155   supportFragmentManager
156     .beginTransaction()
157     .addToBackStack(null)
158     .replace(containerViewId, fragment)
159     .commit()
160 }
161 
FragmentActivitynull162 fun FragmentActivity.removeFragmentNow(fragment: Fragment) {
163   supportFragmentManager
164     .beginTransaction()
165     .remove(fragment)
166     .commitNow()
167 }
168