-
Notifications
You must be signed in to change notification settings - Fork 4.7k
/
LifecycleHelper.kt
60 lines (54 loc) · 2.17 KB
/
LifecycleHelper.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.swmansion.rnscreens
import android.view.View
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
class LifecycleHelper {
private val mViewToLifecycleMap: MutableMap<View, Lifecycle> = HashMap()
private val mRegisterOnLayoutChange: View.OnLayoutChangeListener = object : View.OnLayoutChangeListener {
override fun onLayoutChange(
view: View,
i: Int,
i1: Int,
i2: Int,
i3: Int,
i4: Int,
i5: Int,
i6: Int,
i7: Int
) {
registerViewWithLifecycleOwner(view)
view.removeOnLayoutChangeListener(this)
}
}
private fun registerViewWithLifecycleOwner(view: View) {
val parent = findNearestScreenFragmentAncestor(view)
if (parent != null && view is LifecycleObserver) {
val lifecycle = parent.lifecycle
lifecycle.addObserver((view as LifecycleObserver))
mViewToLifecycleMap[view] = lifecycle
}
}
fun <T> register(view: T) where T : View, T : LifecycleObserver? {
// we need to wait until view is mounted in the hierarchy as this method is called only at the
// moment of the view creation. In order to register lifecycle observer we need to find ancestor
// of type Screen and this can only happen when the view is properly attached. We rely on
// Android's onLayout callback being triggered when the view gets added to the hierarchy and
// only then we attempt to locate lifecycle owner ancestor.
view.addOnLayoutChangeListener(mRegisterOnLayoutChange)
}
fun <T> unregister(view: T) where T : View, T : LifecycleObserver? {
mViewToLifecycleMap[view]?.removeObserver(view)
}
companion object {
fun findNearestScreenFragmentAncestor(view: View): Fragment? {
var parent = view.parent
while (parent != null && parent !is Screen) {
parent = parent.parent
}
return if (parent != null) {
(parent as Screen).fragment
} else null
}
}
}