Skip to content

Commit c511007

Browse files
committed
feat: addListener returns removal function for granular listener control
1 parent 1f325e7 commit c511007

69 files changed

Lines changed: 449 additions & 211 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

android/src/main/java/com/margelo/nitro/rive/BaseHybridViewModelProperty.kt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ import kotlinx.coroutines.flow.Flow
99
@Keep
1010
@DoNotStrip
1111
interface BaseHybridViewModelProperty<T> {
12-
val scope: CoroutineScope?
13-
val job: Job?
14-
val listeners: MutableList<(T) -> Unit>
12+
val scope: CoroutineScope?
13+
val job: Job?
14+
val listeners: MutableMap<String, (T) -> Unit>
1515

16-
fun ensureValueListenerJob(valueFlow: Flow<T>, drop: Int = 0)
17-
fun onChanged(value: T)
18-
fun removeListeners()
19-
fun dispose()
16+
fun ensureValueListenerJob(valueFlow: Flow<T>, drop: Int = 0)
17+
fun onChanged(value: T)
18+
fun addListenerInternal(callback: (T) -> Unit): () -> Unit
19+
fun removeListener(id: String)
20+
fun removeListeners()
21+
fun dispose()
2022
}

android/src/main/java/com/margelo/nitro/rive/BaseHybridViewModelPropertyImpl.kt

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,61 @@ import kotlinx.coroutines.cancel
99
import kotlinx.coroutines.launch
1010
import kotlinx.coroutines.flow.Flow
1111
import kotlinx.coroutines.flow.drop
12+
import java.lang.ref.WeakReference
13+
import java.util.UUID
1214

1315
@Keep
1416
@DoNotStrip
1517
class BaseHybridViewModelPropertyImpl<T> : BaseHybridViewModelProperty<T> {
16-
override var scope: CoroutineScope? = null
17-
override var job: Job? = null
18-
override val listeners = mutableListOf<(T) -> Unit>()
18+
override var scope: CoroutineScope? = null
19+
override var job: Job? = null
20+
override val listeners = mutableMapOf<String, (T) -> Unit>()
1921

2022
override fun ensureValueListenerJob(valueFlow: Flow<T>, drop: Int) {
21-
if (scope == null) {
22-
scope = CoroutineScope(Dispatchers.Default)
23-
}
24-
if (job == null) {
25-
job = scope?.launch {
26-
valueFlow.drop(drop).collect { value ->
27-
onChanged(value)
28-
}
29-
}
23+
if (scope == null) {
24+
scope = CoroutineScope(Dispatchers.Default)
25+
}
26+
if (job == null) {
27+
job = scope?.launch {
28+
valueFlow.drop(drop).collect { value ->
29+
onChanged(value)
3030
}
31+
}
3132
}
33+
}
3234

33-
override fun onChanged(value: T) {
34-
listeners.forEach { listener ->
35-
listener(value)
36-
}
35+
override fun onChanged(value: T) {
36+
listeners.values.forEach { listener ->
37+
listener(value)
3738
}
39+
}
3840

39-
override fun removeListeners() {
40-
listeners.clear()
41-
job?.cancel()
42-
scope?.cancel()
43-
job = null
44-
scope = null
41+
override fun addListenerInternal(callback: (T) -> Unit): () -> Unit {
42+
val id = UUID.randomUUID().toString()
43+
listeners[id] = callback
44+
val weakSelf = WeakReference(this)
45+
return {
46+
weakSelf.get()?.removeListener(id)
4547
}
48+
}
4649

47-
override fun dispose() {
48-
removeListeners()
50+
override fun removeListener(id: String) {
51+
listeners.remove(id)
52+
if (listeners.isEmpty()) {
53+
job?.cancel()
54+
job = null
4955
}
56+
}
57+
58+
override fun removeListeners() {
59+
listeners.clear()
60+
job?.cancel()
61+
scope?.cancel()
62+
job = null
63+
scope = null
64+
}
65+
66+
override fun dispose() {
67+
removeListeners()
68+
}
5069
}

android/src/main/java/com/margelo/nitro/rive/HybridViewModelBooleanProperty.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ class HybridViewModelBooleanProperty(private val viewModelBoolean: ViewModelBool
1515
viewModelBoolean.value = value
1616
}
1717

18-
override fun addListener(onChanged: (value: Boolean) -> Unit) {
19-
listeners.add(onChanged)
18+
override fun addListener(onChanged: (value: Boolean) -> Unit): () -> Unit {
19+
val remover = addListenerInternal(onChanged)
2020
ensureValueListenerJob(viewModelBoolean.valueFlow)
21+
return remover
2122
}
2223
}

android/src/main/java/com/margelo/nitro/rive/HybridViewModelColorProperty.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ class HybridViewModelColorProperty(private val viewModelColor: ViewModelColorPro
1515
viewModelColor.value = value.toInt()
1616
}
1717

18-
override fun addListener(onChanged: (value: Double) -> Unit) {
19-
listeners.add { intValue: Int -> onChanged(intValue.toDouble()) }
18+
override fun addListener(onChanged: (value: Double) -> Unit): () -> Unit {
19+
val remover = addListenerInternal { intValue: Int -> onChanged(intValue.toDouble()) }
2020
ensureValueListenerJob(viewModelColor.valueFlow)
21+
return remover
2122
}
2223
}

android/src/main/java/com/margelo/nitro/rive/HybridViewModelEnumProperty.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ class HybridViewModelEnumProperty(private val viewModelEnum: ViewModelEnumProper
1515
viewModelEnum.value = value
1616
}
1717

18-
override fun addListener(onChanged: (value: String) -> Unit) {
19-
listeners.add(onChanged)
18+
override fun addListener(onChanged: (value: String) -> Unit): () -> Unit {
19+
val remover = addListenerInternal(onChanged)
2020
ensureValueListenerJob(viewModelEnum.valueFlow)
21+
return remover
2122
}
2223
}

android/src/main/java/com/margelo/nitro/rive/HybridViewModelImageProperty.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ class HybridViewModelImageProperty(private val viewModelImage: ViewModelImagePro
1414
viewModelImage.set((image as? HybridRiveImage)?.renderImage)
1515
}
1616

17-
override fun addListener(onChanged: () -> Unit) {
18-
listeners.add(onChanged)
17+
override fun addListener(onChanged: () -> Unit): () -> Unit {
18+
val remover = addListenerInternal { _ -> onChanged() }
1919
ensureValueListenerJob(viewModelImage.valueFlow.map { })
20+
return remover
2021
}
2122
}

android/src/main/java/com/margelo/nitro/rive/HybridViewModelNumberProperty.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ class HybridViewModelNumberProperty(private val viewModelNumber: ViewModelNumber
1616
viewModelNumber.value = value.toFloat()
1717
}
1818

19-
override fun addListener(onChanged: (value: Double) -> Unit) {
20-
listeners.add(onChanged)
19+
override fun addListener(onChanged: (value: Double) -> Unit): () -> Unit {
20+
val remover = addListenerInternal(onChanged)
2121
ensureValueListenerJob(viewModelNumber.valueFlow.map { it.toDouble() })
22+
return remover
2223
}
2324
}

android/src/main/java/com/margelo/nitro/rive/HybridViewModelStringProperty.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ class HybridViewModelStringProperty(private val viewModelString: ViewModelString
1515
viewModelString.value = value
1616
}
1717

18-
override fun addListener(onChanged: (value: String) -> Unit) {
19-
listeners.add(onChanged)
18+
override fun addListener(onChanged: (value: String) -> Unit): () -> Unit {
19+
val remover = addListenerInternal(onChanged)
2020
ensureValueListenerJob(viewModelString.valueFlow)
21+
return remover
2122
}
2223
}

android/src/main/java/com/margelo/nitro/rive/HybridViewModelTriggerProperty.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ class HybridViewModelTriggerProperty(private val viewModelTrigger: ViewModelTrig
1313
viewModelTrigger.trigger()
1414
}
1515

16-
override fun addListener(onChanged: () -> Unit) {
17-
listeners.add { _ -> onChanged() }
16+
override fun addListener(onChanged: () -> Unit): () -> Unit {
17+
val remover = addListenerInternal { _ -> onChanged() }
1818
// We drop the first value as a trigger has no initial value
1919
ensureValueListenerJob(viewModelTrigger.valueFlow, 1)
20+
return remover
2021
}
2122
}

example/android/.kotlin/sessions/kotlin-compiler-12952147549113407283.salive

Whitespace-only changes.

0 commit comments

Comments
 (0)