palette-state-parks-on-loading
The palette holder has no "still valid" state
Extraction is asynchronous, and the state holder that wraps it has three states — Loading, Success,
Error — with palette readable only in Success. The order inside generate() is what makes this
sharp: it assigns Loading before it suspends. So for the whole duration of every generation the
palette reads null, and null resolves to whatever your fallback is — usually black.
That is fine when a generation always finishes. It stops being fine the moment one can be cancelled,
because a cancelled generation never assigns Success and nothing re-runs it. The holder sits on
Loading, palette stays null, and the surface stays on its fallback for as long as the screen lives.
Traps
A restarting effect is a cancelling effect, and the key decides what counts as a reason. Keyed on the bitmap, a generation is only ever interrupted by a newer bitmap — which is exactly when interrupting is correct. Keyed on anything coarser, unrelated changes cancel it: