Limiting Rebuilds
Rebuilds are at the heart of how agui
works. Whenever state changes, the widgets in the tree that may change are updated. However, this is a very naïve system and much of the responsibility for limiting these rebuilds is up to the developer (you). We'll go over the problem, and devise a few solutions for it, however ultimately the decision is up to you.
Builders
Builders are essentially closure-derived widgets. You can create these ad-hoc to limit the scope of rebuilds to a sub-tree of widgets, because they're essentially parent-widgets themselves with their own BuildContext
.
#[functional_widget]
fn widget_with_builder(ctx: &BuildContext) -> BuildResult {
build! {
Builder::new(move |ctx| {
// `ctx` is a new `BuildContext` which will not affect the parent widget
let state = ctx.use_state(|| 0);
build! {
Button {
layout: Layout {
sizing: Sizing::Set { width: 64.0, height 32.0 }
}
}
}
}
}
}
Globals
Another option is utilizing globals. You can create state, then create sub-widgets which listen to that state, resulting in potentially fewer rebuilds of your application with little effort. However, this has the effect of making it difficult to grok exactly what your application is doing if used incorrectly, and potentially makes limiting the scope of rebuilds more troublesome as your application grows. You can read more about it here.
Providers and Consumers
Instead of globals, you can use Providers. This is an optional plugin which makes state available to its subtree of widgets, however it's not free. Whenever a child needs to access the state, it needs to traverse the tree to find a parent which is providing that state. This is often negligable, but as your application grows it may become more pronounced if the children that use the state are deeper in the tree.