Skip to content

Commit 2c8b713

Browse files
committed
fix: fix event manager being shared for multiple views
1 parent 76e0968 commit 2c8b713

File tree

4 files changed

+67
-61
lines changed

4 files changed

+67
-61
lines changed

android/src/main/java/com/animatedobserver/AnimatedObserverEventManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class AnimatedObserverEventManager(private val emitter: (value: Double) -> Unit)
1616
field = value
1717

1818
value?.let {
19-
register(value)
19+
unregister = register(value)
2020
emit()
2121
}
2222
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.animatedobserver
2+
3+
import android.content.Context
4+
import android.util.AttributeSet
5+
import android.view.View
6+
import com.facebook.react.bridge.Arguments
7+
import com.facebook.react.bridge.ReactContext
8+
import com.facebook.react.bridge.WritableMap
9+
import com.facebook.react.uimanager.UIManagerHelper
10+
import com.facebook.react.uimanager.events.Event
11+
12+
class AnimatedObserverView : View {
13+
constructor(context: Context?) : super(context)
14+
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
15+
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
16+
context,
17+
attrs,
18+
defStyleAttr
19+
)
20+
21+
val manager: AnimatedObserverEventManager = AnimatedObserverEventManager({ value ->
22+
val reactContext = context as ReactContext
23+
val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
24+
val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, surfaceId)
25+
?: throw IllegalStateException("$NAME: EventDispatcher is not available for surfaceId: $surfaceId")
26+
27+
eventDispatcher.dispatchEvent(ValueChangeEvent(surfaceId, this.id, value))
28+
})
29+
30+
inner class ValueChangeEvent(
31+
surfaceId: Int, viewId: Int, private val value: Double
32+
) : Event<ValueChangeEvent>(surfaceId, viewId) {
33+
override fun getEventName() = EVENT_ON_CHANGE
34+
35+
override fun getEventData(): WritableMap = Arguments.createMap().apply {
36+
putDouble("value", value)
37+
}
38+
}
39+
40+
companion object {
41+
const val NAME = "AnimatedObserverView"
42+
43+
/**
44+
* On Android, it's necessary to use the `top` prefix for event names
45+
* Otherwise, it doesn't work with `Animated.event` using `useNativeDriver: true`
46+
*/
47+
const val EVENT_ON_CHANGE = "topValueChange"
48+
}
49+
}
Lines changed: 16 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,53 @@
11
package com.animatedobserver
22

3-
import android.util.Log
4-
import android.view.View
5-
import com.facebook.react.bridge.Arguments
6-
import com.facebook.react.bridge.ReactContext
7-
import com.facebook.react.bridge.WritableMap
83
import com.facebook.react.module.annotations.ReactModule
94
import com.facebook.react.uimanager.SimpleViewManager
105
import com.facebook.react.uimanager.ThemedReactContext
11-
import com.facebook.react.uimanager.UIManagerHelper
126
import com.facebook.react.uimanager.ViewManagerDelegate
137
import com.facebook.react.uimanager.annotations.ReactProp
14-
import com.facebook.react.uimanager.events.Event
158
import com.facebook.react.viewmanagers.AnimatedObserverViewManagerDelegate
169
import com.facebook.react.viewmanagers.AnimatedObserverViewManagerInterface
17-
import java.util.concurrent.ConcurrentHashMap
1810

19-
@ReactModule(name = AnimatedObserverViewManager.NAME)
20-
class AnimatedObserverViewManager : SimpleViewManager<View>(),
21-
AnimatedObserverViewManagerInterface<View> {
22-
private val mDelegate: ViewManagerDelegate<View> =
11+
@ReactModule(name = AnimatedObserverView.NAME)
12+
class AnimatedObserverViewManager : SimpleViewManager<AnimatedObserverView>(),
13+
AnimatedObserverViewManagerInterface<AnimatedObserverView> {
14+
private val mDelegate: ViewManagerDelegate<AnimatedObserverView> =
2315
AnimatedObserverViewManagerDelegate(this)
2416

25-
private var manager: AnimatedObserverEventManager? = null;
26-
27-
override fun createViewInstance(context: ThemedReactContext): View {
28-
val view = View(context)
29-
30-
manager?.cleanup()
31-
manager = AnimatedObserverEventManager({ value ->
32-
val reactContext = view.context as ReactContext
33-
val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
34-
val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, surfaceId)
35-
?: throw IllegalStateException("$AnimatedObserverViewManager.NAME: EventDispatcher is not available for surfaceId: $surfaceId")
36-
37-
eventDispatcher.dispatchEvent(ValueChangeEvent(surfaceId, view.id, value))
38-
})
17+
override fun createViewInstance(context: ThemedReactContext): AnimatedObserverView {
18+
val view = AnimatedObserverView(context)
3919

4020
return view;
4121
}
4222

43-
override fun onDropViewInstance(view: View) {
44-
manager?.cleanup()
45-
manager = null
23+
override fun onDropViewInstance(view: AnimatedObserverView) {
24+
view.manager.cleanup()
4625

4726
super.onDropViewInstance(view)
4827
}
4928

5029
override fun prepareToRecycleView(
5130
reactContext: ThemedReactContext,
52-
view: View
53-
): View? {
54-
manager?.cleanup()
55-
manager = null
56-
31+
view: AnimatedObserverView
32+
): AnimatedObserverView? {
5733
return super.prepareToRecycleView(reactContext, view)
5834
}
5935

6036
override fun getDelegate() = mDelegate
6137

62-
override fun getName() = NAME
38+
override fun getName() = AnimatedObserverView.NAME
6339

6440
override fun getExportedCustomDirectEventTypeConstants() = mapOf(
65-
EVENT_ON_CHANGE to mapOf("registrationName" to EVENT_ON_CHANGE)
41+
AnimatedObserverView.EVENT_ON_CHANGE to mapOf("registrationName" to AnimatedObserverView.EVENT_ON_CHANGE)
6642
)
6743

6844
@ReactProp(name = "tag")
69-
override fun setTag(view: View, nextTag: String?) {
70-
manager?.tag = nextTag
45+
override fun setTag(view: AnimatedObserverView, nextTag: String?) {
46+
view.manager.tag = nextTag
7147
}
7248

7349
@ReactProp(name = "value")
74-
override fun setValue(view: View, nextValue: Double) {
75-
manager?.value = nextValue
76-
}
77-
78-
inner class ValueChangeEvent(
79-
surfaceId: Int, viewId: Int, private val value: Double
80-
) : Event<ValueChangeEvent>(surfaceId, viewId) {
81-
override fun getEventName() = EVENT_ON_CHANGE
82-
83-
override fun getEventData(): WritableMap = Arguments.createMap().apply {
84-
putDouble("value", value)
85-
}
86-
}
87-
88-
companion object {
89-
const val NAME = "AnimatedObserverView"
90-
91-
/**
92-
* On Android, it's necessary to use `top` prefix for event names
93-
* Otherwise it doesn't work with `Animated.event` using `useNativeDriver: true`
94-
*/
95-
const val EVENT_ON_CHANGE = "topValueChange"
50+
override fun setValue(view: AnimatedObserverView, nextValue: Double) {
51+
view.manager.value = nextValue
9652
}
9753
}

example/src/Examples.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export function AnimatedToReanimated() {
3939
<View style={styles.container}>
4040
<AnimatedConverter from={positionAnimated} to={positionReanimated} />
4141
<AnimatedConverter
42+
name="PositionAnimatedInterpolated"
4243
from={positionAnimatedInterpolated}
4344
to={positionReanimatedInterpolated}
4445
/>

0 commit comments

Comments
 (0)