In Flutter, a widget is the fundamental building block of the user interface. Everything you see on the screen, from a simple text label or button to complex layouts and animations, is a widget. Widgets are immutable descriptions of parts of the user interface. They describe how your app's view should look given its current configuration and state.
Flutter's UI is composed of a tree of nested widgets. Each widget is a part of the parent widget, creating a hierarchical structure. Complex user interfaces are built by composing simpler widgets together. For example, a typical Flutter app might have a widget tree starting with an App widget at the root, containing a Scaffold widget, which in turn contains an AppBar and a Body. The Body might contain a Column with multiple child widgets like Buttons and Images.
Flutter has two main types of widgets: StatelessWidget and StatefulWidget. StatelessWidget is immutable and cannot change over time. It rebuilds only when its parent widget changes. StatelessWidgets are used for static UI elements like text labels or icons. On the other hand, StatefulWidget is mutable and can change over time. It maintains state that can change during the lifetime of the widget. StatefulWidgets are used for dynamic UI elements like form inputs or animations. In the code example, we can see how each type is implemented. The StatelessWidget simply renders based on its constructor parameters, while the StatefulWidget maintains a count variable that can be updated through the setState method.
Widgets in Flutter go through a lifecycle from creation to disposal. For a StatefulWidget, the lifecycle begins when the widget is created. Then, the initState method is called once when the widget is inserted into the widget tree. This is where you initialize state variables and subscribe to streams or other data sources. Next, the build method is called to render the widget. When a parent widget changes, didUpdateWidget is called, allowing you to respond to changes in configuration. When setState is called, the framework marks the widget as dirty and schedules a rebuild. Finally, when the widget is removed from the tree, dispose is called, where you should clean up any resources. In this example, we can see how a counter app's state changes when the increment button is pressed, triggering a rebuild of the UI.
To summarize what we've learned about widgets in Flutter: First, widgets are the fundamental building blocks of the Flutter user interface. Everything visible on screen is a widget. Second, Flutter uses a hierarchical widget tree to compose complex interfaces from simpler components. Third, there are two main types of widgets: StatelessWidget for static UI elements that don't change over time, and StatefulWidget for dynamic elements that can change based on user interaction or other events. Fourth, widgets follow a lifecycle from creation to disposal, with different methods called at each stage. Understanding widgets is essential for developing Flutter applications, as they form the core of Flutter's declarative UI approach.