Skip to content

Commit

Permalink
Fixed crash on switching between the screens
Browse files Browse the repository at this point in the history
Fix is taken from rive-app#205

We will be using this forked repo until the PR is merged to the original repo
  • Loading branch information
azmatullahqau committed Oct 5, 2023
1 parent 984f7b2 commit 6789b56
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
51 changes: 50 additions & 1 deletion android/src/main/java/com/rivereactnative/RiveReactNativeView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package com.rivereactnative
import android.widget.FrameLayout
import app.rive.runtime.kotlin.PointerEvents
import app.rive.runtime.kotlin.RiveAnimationView
import app.rive.runtime.kotlin.controllers.ControllerState
import app.rive.runtime.kotlin.controllers.ControllerStateManagement
import app.rive.runtime.kotlin.controllers.RiveFileController
import app.rive.runtime.kotlin.core.*
import app.rive.runtime.kotlin.core.errors.*
Expand All @@ -23,7 +25,7 @@ import java.io.UnsupportedEncodingException


class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout(context) {
private var riveAnimationView: RiveAnimationView = RiveAnimationView(context)
private var riveAnimationView: RiveAnimationView
private var resId: Int = -1
private var url: String? = null
private var animationName: String? = null
Expand All @@ -35,6 +37,8 @@ class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout
private var shouldBeReloaded = true
private var exceptionManager: ExceptionsManagerModule? = null
private var isUserHandlingErrors = false
@OptIn(ControllerStateManagement::class)
private var controllerState: ControllerState? = null;

enum class Events(private val mName: String) {
PLAY("onPlay"),
Expand All @@ -51,6 +55,7 @@ class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout
}

init {
riveAnimationView = RiveAnimationView(context)
val listener = object : RiveFileController.Listener {
override fun notifyLoop(animation: PlayableInstance) {
if (animation is LinearAnimationInstance) {
Expand Down Expand Up @@ -108,6 +113,50 @@ class RiveReactNativeView(private val context: ThemedReactContext) : FrameLayout
addView(riveAnimationView)
}

@OptIn(ControllerStateManagement::class)
fun dispose() {
removeView(riveAnimationView)
controllerState?.dispose();
}

@OptIn(ControllerStateManagement::class)
override fun onAttachedToWindow() {
// The below solves: https://github.com/rive-app/rive-react-native/issues/198
// When the view is returned to, we reuse the view's resources.
// For example, navigating to a new page and returning, or a TabView.
controllerState?.let {
riveAnimationView.restoreControllerState(it);
// The controller refCount is a combination of the creation of the controller and the
// initialization of the RiveArtboardRenderer (which calls acquire on the controller).

// This could be decoupled in future versions of the Android runtime, and this code
// may require updating.
//
// For now we're doing a safety check to only add an additional acquire if the refCount is 0.
// As the RiveFileController would automatically have incremented the refCount on instantiation,
// and decreased when navigating away. It's safe to assume it should not be 0 at this point as
// the view still exists.
if (riveAnimationView.controller.refCount == 0) {
riveAnimationView.controller.acquire();
// Another approach would be to recreate the entire RiveAnimationView and call addView again.
// But this does not work great due to this issue: https://github.com/facebook/react-native/issues/17968
// Additionally, it may not be the most optimal route as the entire view needs to be recreated
// including all of the attached resources.
}

// Re-add the view
addView(riveAnimationView)
}
super.onAttachedToWindow()
}

@OptIn(ControllerStateManagement::class)
override fun onDetachedFromWindow() {
controllerState = riveAnimationView?.saveControllerState();
removeView(riveAnimationView)
super.onDetachedFromWindow()
}

fun onPlay(animationName: String, isStateMachine: Boolean = false) {
val reactContext = context as ReactContext

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ class RiveReactNativeViewManager : SimpleViewManager<RiveReactNativeView>() {
return RiveReactNativeView(reactContext)
}

override fun onDropViewInstance(view: RiveReactNativeView) {
view.dispose();
super.onDropViewInstance(view)
}

override fun onAfterUpdateTransaction(view: RiveReactNativeView) {
super.onAfterUpdateTransaction(view)
view.update()
Expand Down

0 comments on commit 6789b56

Please sign in to comment.