diff --git a/android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt b/android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt index 7678469e..f379337f 100644 --- a/android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt +++ b/android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt @@ -1,6 +1,5 @@ package com.margelo.nitro.rive -import android.util.Log import androidx.annotation.Keep import com.facebook.proguard.annotations.DoNotStrip import com.facebook.react.uimanager.ThemedReactContext @@ -148,6 +147,7 @@ class HybridRiveView(val context: ThemedReactContext) : HybridRiveViewSpec() { afterUpdate() } + override fun afterUpdate() { logged(TAG, "afterUpdate") { val hybridFile = file as? HybridRiveFile diff --git a/android/src/main/java/com/rive/RivePackage.kt b/android/src/main/java/com/rive/RivePackage.kt index e3648436..7b61074f 100644 --- a/android/src/main/java/com/rive/RivePackage.kt +++ b/android/src/main/java/com/rive/RivePackage.kt @@ -6,12 +6,11 @@ import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.module.model.ReactModuleInfoProvider import com.facebook.react.uimanager.ViewManager import com.margelo.nitro.rive.riveOnLoad -import com.margelo.nitro.rive.views.HybridRiveViewManager class RivePackage : BaseReactPackage() { override fun createViewManagers(reactContext: ReactApplicationContext): List> { val viewManagers: MutableList> = ArrayList() - viewManagers.add(HybridRiveViewManager()) + viewManagers.add(RiveViewManager()) return viewManagers } override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? { diff --git a/android/src/main/java/com/rive/RiveReactNativeView.kt b/android/src/main/java/com/rive/RiveReactNativeView.kt index 015e1390..cdc00515 100644 --- a/android/src/main/java/com/rive/RiveReactNativeView.kt +++ b/android/src/main/java/com/rive/RiveReactNativeView.kt @@ -2,9 +2,13 @@ package com.rive import android.annotation.SuppressLint import android.widget.FrameLayout -import com.facebook.react.uimanager.ThemedReactContext +import androidx.lifecycle.LifecycleObserver +import androidx.lifecycle.LifecycleOwner import app.rive.runtime.kotlin.RiveAnimationView +import app.rive.runtime.kotlin.RiveViewLifecycleObserver import app.rive.runtime.kotlin.controllers.RiveFileController +import app.rive.runtime.kotlin.core.RefCount +import com.facebook.react.uimanager.ThemedReactContext import app.rive.runtime.kotlin.core.Alignment import app.rive.runtime.kotlin.core.File import app.rive.runtime.kotlin.core.Fit @@ -40,18 +44,58 @@ data class ViewConfiguration( val bindData: BindData ) +class ReactNativeRiveViewLifecycleObserver(dependencies: MutableList) : + RiveViewLifecycleObserver(dependencies) { + @SuppressLint("MissingSuperCall") + override fun onDestroy(owner: LifecycleOwner) { + owner.lifecycle.removeObserver(this) + } + + fun dispose() { + dependencies.forEach { it.release() } + dependencies.clear() + } +} + +@SuppressLint("ViewConstructor") +class ReactNativeRiveAnimationView(context: ThemedReactContext) : RiveAnimationView(context) { + fun dispose() { + (lifecycleObserver as ReactNativeRiveViewLifecycleObserver).dispose() + } + + @SuppressLint("VisibleForTests") + override fun createObserver(): LifecycleObserver { + return ReactNativeRiveViewLifecycleObserver( + listOfNotNull(controller, rendererAttributes.assetLoader).toMutableList() + ) + } +} + @SuppressLint("ViewConstructor") class RiveReactNativeView(context: ThemedReactContext) : FrameLayout(context) { - internal var riveAnimationView: RiveAnimationView? = null + internal var riveAnimationView: ReactNativeRiveAnimationView? = null private var eventListeners: MutableList = mutableListOf() private val viewReadyDeferred = CompletableDeferred() private var _activeStateMachineName: String? = null + private var willDispose = false init { - riveAnimationView = RiveAnimationView(context) + riveAnimationView = ReactNativeRiveAnimationView(context) addView(riveAnimationView) } + fun dispose() { + willDispose = true + } + + override fun onDetachedFromWindow() { + if (willDispose) { + riveAnimationView?.dispose() + removeEventListeners() + } + super.onDetachedFromWindow() + } + //region Public Methods (API) suspend fun awaitViewReady(): Boolean { return viewReadyDeferred.await() diff --git a/android/src/main/java/com/rive/RiveViewManager.kt b/android/src/main/java/com/rive/RiveViewManager.kt new file mode 100644 index 00000000..16bbef08 --- /dev/null +++ b/android/src/main/java/com/rive/RiveViewManager.kt @@ -0,0 +1,11 @@ +package com.rive + +import android.view.View +import com.margelo.nitro.rive.views.HybridRiveViewManager + +class RiveViewManager : HybridRiveViewManager() { + override fun onDropViewInstance(view: View) { + (view as? RiveReactNativeView)?.dispose() + super.onDropViewInstance(view) + } +}