new ViewC(...) b.add(c3) // Declarative style return ViewB( color: red, child: const ViewC(), ); In order to lighten the burden on developers from having to program how to transition between various UI states, Flutter, by contrast, lets the developer describe the current UI state and leaves the transitioning to the framework like opacity animation.
build method of a stateless widget is typically only called in three situations: ◦ the first time the widget is inserted in the tree ◦ when the widget's parent changes its configuration ◦ when an InheritedWidget it depends on changes • Sub widgets can change like Stream widget • If the 2nd and 3rd happen frequently, isolate the widget to optimize the performance class Frog extends StatelessWidget { const Frog({ Key? key, this.color = const Color(0xFF2DBD3A), this.child, }) : super(key: key); final Color color; final Widget? child; @override Widget build(BuildContext context) { return Container(color: color, child: child); } }
is information that: ◦ Can be read synchronously when the widget is built ◦ Might change during the lifetime of the widget • Notify state changes using State.setState • Calling setState notifies the framework that the internal state of this object has changed, and it rebuilds the whole widget • It is an error to call setState in build method or after the framework calls dispose, so use if(mounted) if you use it in async function
InheritedWidgets. These will typically rebuild many times during the application's lifetime • Push the state to the leaves • If a subtree does not change, cache the widget (By final or const) that represents that subtree and re-use it each time it can be used • Avoid changing the depth of any created subtrees or changing the type of any widgets in the subtree • In general, avoid using stateful widget except for ui only use-case like animations or app lifecycle Bad Structure Example Vs Better Structure Example
down the tree, like Theme.of(context) • To obtain the nearest instance of a particular type of inherited widget from a build context, use BuildContext.dependOnInheritedWid getOfExactType. • Inherited widgets, when referenced in this way, will cause the consumer to rebuild when the inherited widget itself changes state
frequently • Widget 2 is not dependent on the state of its parent InheritedWidget • So widget 2 always rebuilds itself because of widget 1 • Isolate widget 1 and its state from the other widgets
(sometimes called UI state or local state) is the state you can neatly contain in a single widget like: ◦ current page in a PageView ◦ current progress of a complex animation ◦ current selected tab in a BottomNavigationBar • State that is not ephemeral, that you want to share across many parts of your app, and that you want to keep between user sessions, is what we call application state like the shopping cart in an e-commerce app • There are two conceptual types of state in any Flutter app: ◦ Ephemeral state can be implemented using State and setState(), and is often local to a single widget ◦ The rest is your app state
of the cart. final List<Item> _items = []; /// An unmodifiable view of the items in the cart. UnmodifiableListView<Item> get items => UnmodifiableListView(_items); /// The current total price of all items (assuming all items cost $42). int get totalPrice => _items.length * 42; /// Adds [item] to cart. This and [removeAll] are the only ways to modify the /// cart from the outside. void add(Item item) { _items.add(item); // This call tells the widgets that are listening to this model to rebuild. notifyListeners(); } /// Removes all items from the cart. void removeAll() { _items.clear(); // This call tells the widgets that are listening to this model to rebuild. notifyListeners(); } }
flutter framework • Suitable for the simple and small features like theming, navigation, fonts, localization Disadvantages: • Using StatefulWidget • Boilerplate of writing each InheritedWidget and adding and removing listeners
• A wrapper around InheritedWidget to make them easier to use and more reusable. • Simplified allocation/disposal of resources • A vastly reduced boilerplate over making a new class every time • But it’s hard to implement a design pattern or architecture
design patterns is to separate Data Model and View, why: • Make a clean structure for beautiful and easy to read • More comprehensible business logic • Separate features to simultaneously programming • Using reusable components • High scalability • Writing test for each component
what you choose, business requirements should be in the priority, like: • Speed • Scalability • Performance • Stability • Maintainability • Quality • Quantity