How does GetX's Obx widget know when to rebuild?
Short Answer
Obx subscribes to any .obs observable read inside its builder function during the build — it tracks reads via a global tracking mechanism, rather than requiring you to explicitly declare which values it depends on.
Unlike Provider's Consumer<T> (explicitly typed to one provider) or Riverpod's ref.watch() (explicitly registers a dependency per call), GetX's Obx(() => Text('\${counter.value}')) figures out its dependencies implicitly: when the builder function runs, reading .value on any Rx/.obs variable registers that observable with the currently-building Obx instance, similar in spirit to how MobX or Vue's reactivity system works.
In practice, this means Obx only rebuilds when an observable it actually read last time changes — but it can't detect a dependency it didn't read on the previous build (e.g. a value only read inside a conditional branch that wasn't taken), a subtle source of 'why didn't this rebuild' bugs.
Common Mistakes
- ×Reading an observable conditionally inside Obx, then being surprised the widget doesn't rebuild when that branch wasn't taken during the last build.
- ×Nesting Obx widgets unnecessarily instead of one Obx wrapping the whole reactive section.