You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(android): keep a strong reference to the fallback font picker - #405
rive-android keeps FontFallbackStrategy.stylePicker only in a WeakReference (still the case in 11.12.1), and HybridRiveFontConfig.applyFallbackFonts() passed it an anonymous object nothing else held. A GC shortly after setFallbackFonts() collected the picker, so text needing a fallback (Thai, Hebrew, Arabic, CJK) rendered blank with FindFontFallback - no fallback found. This keeps a strong reference until clearFallbackFonts(). Affects both Android runtimes, since the file is shared.
Root cause and fix by @edgartoomikw in #369, thanks!
Adds an Issue369FontPickerGC reproducer page: it sets Kanit as the fallback, loads the font another 250 times to make the Java heap collect, then mounts a view showing Thai text. On the Pixel 6 emulator with rive-android 11.12.1, the text is blank without the fix and renders in Kanit with it.
rive-android stores FontFallbackStrategy.stylePicker in a WeakReference,
so the anonymous picker was collected at the next GC and fallback fonts
silently stopped working (#369).
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Overlapping font updates can leave the installed picker unretained, and stale reproducer runs can overwrite Reset or restart state because cancellation and font setup are not safely coordinated.
This PR addresses #369 by retaining the Android fallback-font picker, preventing garbage collection from disrupting non-Latin text rendering. The shared implementation covers both Android runtimes.
Changes:
Keep a strong reference to the fallback picker until clearFallbackFonts().
Add a Thai-text reproducer that repeatedly loads Kanit to trigger garbage collection before rendering.
Concurrent applyFallbackFonts/clearFallbackFonts calls run on
Dispatchers.Default and could interleave the strong-ref and stylePicker
writes, leaving rive-android weakly holding a picker nobody else retains.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Reset and restart can let a cancelled run resume after an await, corrupt progress, or mount ThaiText before the replacement run completes setup, requiring per-run cancellation checks or serialized restarts.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Prevent stale run from resuming after reset and restart
Reset followed by Start reuses running.current, allowing an older run to resume after an await and update progress or mount ThaiText before the replacement run finishes fallback setup and GC churn. Reset alone can also leave the cancelled run reporting churning with 250 loads. Use a per-run generation token invalidated by reset/unmount and checked after each await, or serialize restarts until the previous run exits.
Navigating away without pressing Reset leaves Kanit installed as the process-wide fallback: cancel() only invalidates the run, while the new native strong reference keeps the picker and its fonts alive. Subsequent example pages therefore inherit this reproducer's font configuration. Please also enqueue clearFallbackFonts() during cleanup, after cancelling the run, so leaving the page removes its global side effects.
Prevent reset or unmount from restarting after font clearing
If Reset is pressed while this Start handler awaits native font clearing, the handler still resumes and creates a fresh run, overriding Reset and eventually mounting the view again. Unmounting during the same wait can also restart font setup. Capture the run ID after invoking reset() and check it before calling start() so cancellation also covers this pending restart.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
rive-android keeps
FontFallbackStrategy.stylePickeronly in aWeakReference(still the case in 11.12.1), andHybridRiveFontConfig.applyFallbackFonts()passed it an anonymous object nothing else held. A GC shortly aftersetFallbackFonts()collected the picker, so text needing a fallback (Thai, Hebrew, Arabic, CJK) rendered blank withFindFontFallback - no fallback found. This keeps a strong reference untilclearFallbackFonts(). Affects both Android runtimes, since the file is shared.Root cause and fix by @edgartoomikw in #369, thanks!
Adds an
Issue369FontPickerGCreproducer page: it sets Kanit as the fallback, loads the font another 250 times to make the Java heap collect, then mounts a view showing Thai text. On the Pixel 6 emulator with rive-android 11.12.1, the text is blank without the fix and renders in Kanit with it.Fixes #369