Skip to content

Commit

Permalink
RiveAnimationView.setAssetLoader() fix
Browse files Browse the repository at this point in the history
Manages custom asset loader resources appropriately when setting directly it on the View.

A couple of important points:
- `RiveAnimationView.setAssetLoader()` will `acquire()` the resources to keep the ref count alive, since an AssetLoader is a C++
- If people are using this setter when creating the View, it's much/easier to use the Builder Pattern like [here](https://github.com/rive-app/rive/blob/938fc451265aa02edd17d690ac5cae1b40cfd91e/packages/runtime_android/app/src/androidTest/java/app/rive/runtime/example/RiveBuilderTest.kt#L156-L189)

Diffs=
38304fe8b `RiveAnimationView.setAssetLoader()` fix (#6685)

Co-authored-by: Umberto Sonnino <[email protected]>
  • Loading branch information
umberto-sonnino and umberto-sonnino committed Feb 28, 2024
1 parent a62470b commit fdbec71
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ffde4f5f66e868c3929de24bb0856db7d1d01e95
38304fe8b37f20a882317a59423d388b6176a745
18 changes: 9 additions & 9 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ android {
}
namespace 'app.rive.runtime.example'
composeOptions {
kotlinCompilerExtensionVersion '1.4.7'
kotlinCompilerExtensionVersion '1.5.10'
}
packagingOptions {
resources {
Expand All @@ -70,26 +70,26 @@ dependencies {
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.fragment:fragment-ktx:1.6.1'
implementation 'androidx.fragment:fragment-ktx:1.6.2'
debugImplementation project(path: ':kotlin')
releaseImplementation project(path: ':kotlin')
previewImplementation 'app.rive:rive-android:+'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
implementation 'com.google.android.material:material:1.10.0'
implementation 'androidx.activity:activity-compose:1.8.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.activity:activity-compose:1.8.2'
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.compose.material3:material3:1.2.0-alpha09'
implementation 'androidx.compose.material3:material3:1.2.0'
implementation 'androidx.startup:startup-runtime:1.1.1'
implementation 'com.android.volley:volley:1.2.1'
implementation "org.jetbrains.kotlin:kotlin-reflect:1.8.22"
implementation 'org.jetbrains.kotlin:kotlin-reflect:1.9.22'

testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.5.3"
androidTestImplementation 'androidx.compose.ui:ui-test-junit4:1.6.2'
androidTestImplementation project(path: ':kotlin')
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.13'
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4
import app.rive.runtime.kotlin.RiveAnimationView
import app.rive.runtime.kotlin.controllers.RiveFileController
import app.rive.runtime.kotlin.core.ContextAssetLoader
import app.rive.runtime.kotlin.core.File
import app.rive.runtime.kotlin.core.FileAsset
import app.rive.runtime.kotlin.core.FileAssetLoader
import app.rive.runtime.kotlin.core.RendererType
import app.rive.runtime.kotlin.core.errors.RiveException
import org.junit.Assert.*
Expand Down Expand Up @@ -47,6 +50,43 @@ class RiveActivityLifecycleTest {
assertNull(controller.activeArtboard)
}

@Test
fun withCustomLoader() {
val activityScenario = ActivityScenario.launch(SingleActivity::class.java);
lateinit var riveView: RiveAnimationView
lateinit var controller: RiveFileController
var assetLoader : FileAssetLoader? = null
// Start the Activity.
activityScenario.onActivity {
riveView = it.findViewById(R.id.rive_single)
controller = riveView.controller

assetLoader = riveView.rendererAttributes.assetLoader
assertTrue(assetLoader!!.hasCppObject)

val nopAssetLoader = object : ContextAssetLoader(it) {
override fun loadContents(asset: FileAsset, inBandBytes: ByteArray): Boolean = true
}
riveView.setAssetLoader(nopAssetLoader)
// release()'d the old one
assertFalse(assetLoader!!.hasCppObject)
assertNotNull(riveView.rendererAttributes.assetLoader)
assetLoader = riveView.rendererAttributes.assetLoader
}
// Close it down.
activityScenario.close()
// Background thread deallocates asynchronously.
waitUntil(1500.milliseconds) { controller.refCount == 0 }
assertFalse(controller.isActive)
assertNull(controller.file)
assertNull(controller.activeArtboard)

// New assetLoader needs to be freed by the creator
assertTrue(assetLoader!!.hasCppObject)
assetLoader?.release()
assertFalse(assetLoader!!.hasCppObject)
}

@Test
fun activityWithRiveViewSetsWrongFileType() {
val activityScenario = ActivityScenario.launch(SingleActivity::class.java);
Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ ext {
}
buildscript {
ext {
gradle_version = '8.1.3'
kotlin_version = "1.8.21"
gradle_version = '8.2.2'
kotlin_version = '1.9.22'
dokkaVersion = "1.4.30"
compose_version = '1.5.3'
compose_version = '1.6.2'
}

repositories {
Expand Down
2 changes: 1 addition & 1 deletion compatibilitytest/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ android {
dependencies {
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.10.0'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

implementation project(path: ':kotlin')
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Wed Oct 13 16:33:42 BST 2021
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
1 change: 0 additions & 1 deletion kotlin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.12.0'
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.getkeepsafe.relinker:relinker:1.4.5'
implementation 'androidx.startup:startup-runtime:1.1.1'
Expand Down
30 changes: 25 additions & 5 deletions kotlin/src/main/java/app/rive/runtime/kotlin/RiveAnimationView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -765,13 +765,25 @@ open class RiveAnimationView(context: Context, attrs: AttributeSet? = null) :

/**
* Overrides the current asset loader.
* It increases the [assetLoader] ref count by one, but its ownership is still
* in the hands of the caller.
*
* A RiveView creates a [FallbackAssetLoader] by default.
*/
fun setAssetLoader(assetLoader: FileAssetLoader?) {
if (assetLoader != rendererAttributes.assetLoader) {
rendererAttributes.assetLoader?.release()
rendererAttributes.assetLoader = assetLoader
if (assetLoader == rendererAttributes.assetLoader) {
return
}

val currentAssetLoader = rendererAttributes.assetLoader
rendererAttributes.assetLoader = assetLoader

currentAssetLoader?.release()
assetLoader?.acquire()

(lifecycleObserver as? RiveViewLifecycleObserver)?.let { depObserver ->
currentAssetLoader?.let { old -> depObserver.remove(old) }
assetLoader?.let { new -> depObserver.insert(new) }
}
}

Expand All @@ -788,7 +800,7 @@ open class RiveAnimationView(context: Context, attrs: AttributeSet? = null) :

override fun createObserver(): LifecycleObserver {
return RiveViewLifecycleObserver(
dependencies = listOfNotNull(controller, rendererAttributes.assetLoader)
dependencies = listOfNotNull(controller, rendererAttributes.assetLoader).toMutableList()
)
}

Expand Down Expand Up @@ -993,7 +1005,7 @@ open class RiveAnimationView(context: Context, attrs: AttributeSet? = null) :
* updated within [RiveAnimationView.onAttachedToWindow]. If there is a new [LifecycleOwner]
* [onCreate], [onStart], and [onResume] will be called again when it is registered.
*/
class RiveViewLifecycleObserver(private val dependencies: List<RefCount>) :
class RiveViewLifecycleObserver(private val dependencies: MutableList<RefCount>) :
DefaultLifecycleObserver {
override fun onCreate(owner: LifecycleOwner) {}

Expand All @@ -1016,6 +1028,14 @@ class RiveViewLifecycleObserver(private val dependencies: List<RefCount>) :
dependencies.forEach { it.release() }
owner.lifecycle.removeObserver(this)
}

fun remove(dependency: RefCount): Boolean {
return dependencies.remove(dependency)
}

fun insert(dependency: RefCount) {
dependencies.add(dependency)
}
}

// Custom Volley request to download and create rive files over http
Expand Down

0 comments on commit fdbec71

Please sign in to comment.