rive-app / rive-app/rive-android

Auto-play inconsistency: controller state-setter helpers restart the render loop, while ViewModel*Property updates (Boolean/Number/Trigger/…) do not

Open
#384 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

triage
Dominant language
Kotlin
Stars
538
Forks
66
PR merge metrics
No merged PRs in 30d

Description

Description

rive-android offers two main ways to drive a State Machine at runtime:

API family Typical call Affects Behaviour when the render loop is idle
Controller helpers setBooleanState(), setNumberState(), setStringState(), setSMTriggerState() StateMachineInstance inputs Ends with queueInput()onStart?.invoke()RiveAnimationView.play()render loop restarts automatically
ViewModel properties vmi.getBooleanProperty("flag").value = true
vmi.getTriggerProperty("pulse").trigger() (same for Number / String / Enum)
ViewModel → data-bind → State Machine Only pushes the value or TriggerUnit; does not call requestAdvance() or play()

With autoplay = false (or after view.pause()), a controller helper immediately shows the change, whereas any ViewModel*Property update has no visible effect until the render loop is restarted manually (riveView.play() or controller.requestAdvance()).
This asymmetry forces developers to add extra code only for ViewModel properties, which is error-prone.


Reproduction
class ReproActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val rive = RiveAnimationView(this).apply {
            setRiveResource(R.raw.machine_demo) // State Machine has Boolean "flag" and Trigger "pulse"
        }
        setContentView(rive)

        // 1️⃣ Controller helper → immediately visible
        rive.controller.setBooleanState("machine", "flag", true)

        val vmi = rive.controller.activeArtboard!!.viewModelInstance

        // 2️⃣ ViewModelBooleanProperty → no visible change
        vmi.getBooleanProperty("flag")?.value = false

        // 3️⃣ ViewModelTriggerProperty → no visible change
        vmi.getTriggerProperty("pulse")?.trigger()
    }
}

Any .riv exposing a Boolean input flag and Trigger input pulse, both bound through the State Machine and the ViewModel, reproduces the issue.


Expected behaviour

All public input APIs should follow one consistent contract:

Option Summary Pros Cons
A — align behaviour (non-breaking) Make every ViewModel*Property update internally call onStart?.invoke() / requestAdvance() No extra boiler‑plate; intuitive Slight behaviour change
B — pure setters for everyone (breaking) Remove implicit auto‑play from controller helpers; callers must restart the loop explicitly APIs become orthogonal (“set value” vs “play”) Breaking change
C — explicit opt-in Add an autoPlay parameter (default = true) to both families so behaviour is explicit and symmetrical Backwards‑compatible; clear intent Larger API surface

Device & versions
Item Version
rive-android 10.1.6
Device samsung SM-F741Q
Android SDK 34 (Android 14)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the controller state-setter helpers and the ViewModel Boolean, Number, String, Enum, and Trigger property updates described in the issue. Reproduce with autoplay disabled or after pausing the view, then determine which consistency option is accepted; done means both API families follow the selected contract and the reproduction behaves consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, kotlin
Domain
mobile
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.