Singletons ghost @State.
Look, I’ve chased enough framework rabbits down Silicon Valley holes to know: state management sounds simple until it isn’t. HarmonyOS developers — yeah, you building for Huawei’s walled garden — hit this wall hard. Slap @State on a singleton instance, tweak its guts from Page2, hop back to Index, and… crickets. No UI refresh. It’s like the compiler’s saying, “Change the variable, not its innards, punk.”
Why Does @State Ignore Your Singleton’s Heartbeat?
@State tracks the variable itself flipping — not the properties dancing inside a class. Straight from the docs, or whatever passes for them in HarmonyOS land: “.NETs
When a singleton class instance is decorated with @State, changing its internal properties does not trigger a UI refresh. For example: in Page2, after toggling the color and returning to the Index page, the UI does not update accordingly.”
That’s the trap. Your VoiceReadHelper singleton — isSpeaking toggles all day — but ArkUI yawns. Twenty years ago, this was AngularJS digest cycle hell. Today? HarmonyOS forcing you to earn reactivity. (Spoiler: most won’t.)
But.
Fix one: @Observed on the class. Sprinkle that fairy dust, and boom — properties become watchable. ArkUI peers inside, spots the flip, repaints. Here’s the code tweak:
@Observed
export class VoiceReadHelper {
// ... rest unchanged
}
Simple. Cynical me asks: why split hairs between @State and @Observed? Huawei’s layering reactivity like onion skins — smells like overengineering to me.
Is AppStorage the Real Singleton Savior?
Or skip @Observed, shove the instance into AppStorage on creation. Pages link via @StorageLink, and changes ripple app-wide. Two-way sync, no sweat.
// In getInstance
AppStorage.setOrCreate('VoiceReadHelper', VoiceReadHelper.instance)
Then in components:
@StorageLink('voiceReadHelper') voiceReadHelper: VoiceReadHelper = VoiceReadHelper.getInstance()
Click in Index, green box. Hop to Page2, toggle, back — still green. Magic? Nah, just storage glue. But here’s my unique dig: this mirrors Electron’s IPC hacks for cross-window state. HarmonyOS isn’t inventing wheels; it’s bolting old ones to a smartphone OS. Who profits? Huawei devs grinding configs, not you.
Picture theme switching. Dark mode singleton. User flips in settings page — every screen syncs without @Observed spaghetti. Notifications too. User prefs. Solid use cases, if you’re buying Huawei’s ecosystem lock-in.
Short para: It works.
Longer riff: But let’s not kid ourselves — singletons scream global mutable state, the original sin of app dev. I’ve seen React apps crumble under Context hell from this. HarmonyOS? Same vibe, fancier decorators. Prediction: six months, forums flood with “@StorageLink leaks memory” threads. Mark it.
And the PR spin? Huawei touts ArkUI as declarative bliss. Reality: hunt these gotchas or ship stale UIs. Seen it since Flexbox launch — frameworks promise, docs bury.
Does @Observed Outshine AppStorage for Speed?
Nah. @Observed keeps it in-memory, snappier for hot paths. AppStorage persists, shares across pages — heavier, but survives navigation. Tradeoff city.
Toggle isSpeaking 100x? @Observed wins. App reboot, state gone? AppStorage laughs. Pick poison.
Real talk: for VoiceReadHelper-like utils, @Observed. App-wide prefs? Storage. Don’t singleton everything — that’s how you end up debugging “why did my theme nuke on page 17?”
One sentence: Test it.
Deeper: Back in 2010, covering iOS storyboards, Apple hid state quirks too. Devs rage-quit. Huawei’s playing same game — shiny NEXT OS, rusty edges. My bet: third-party state libs sprout by Q2, open-source forking ArkUI reactivity. Who’s making money? Not you, grinding docs at 2am.
FAQ
What causes @State singleton UI refresh failure in HarmonyOS?
@State watches the variable reference, not inner props. Use @Observed or AppStorage/@StorageLink.
How to share singleton state across HarmonyOS pages?
AppStorage.setOrCreate on init, @StorageLink in components. Auto-syncs toggles.
@Observed vs AppStorage: which for theme switching?
@Observed for speed, AppStorage for persistence and multi-page glue.