Widgets
Widgets are the reusable building blocks of your app’s user interface. It is important to design them to be readable, maintainable, performant, and testable. By following these principles, you can ensure a smooth development process and a high-quality user experience.
Page/Views
Each page should be composed of two classes: a Page
, which is responsible for defining the page’s route and gathering all the dependencies needed from the context; and a View
, where the “real” implementation of the UI resides.
Distinguishing between a Page
and its View
allows the Page
to provide dependencies to the View
, enabling the view’s dependencies to be mocked when testing.
We can easily write tests for the LoginView
by mocking the LoginBloc
and providing it directly to the view.
Use standalone Widgets over helper methods
If a Widget starts growing with complexity, you might want to split the build method up. Instead of creating a function, simply create a new Widget.
The recommended approach is to create an entirely separate class for your widget.
Avoid creating a method that returns a widget.
Why Create a New Widget?
Creating a new widget provides several benefits over using a helper method:
- Testability: You can write widget tests for the
MyText
widget without worrying aboutMyWidget
or any of the dependencies that it might require. - Maintainability: Smaller widgets are easier to maintain and aren’t coupled to their parent widget. These widgets will also have their own BuildContext, so you don’t have to worry about using the wrong or an invalid context.
- Reusability: Creating new widgets allows you to easily reuse the widget to compose larger widgets.
- Performance: Using a helper method to return a widget that could update the state could cause unnecessary rebuilds of the entire widget. Imagine that the
Text
widget triggered an animation when tapped. We would need to callsetState()
, which would rebuildMyWidget
and all of its children. If this functionality were encapsulated in theMyText
widget, only theMyText
widget would be rebuilt when theText
is tapped.
The Flutter team has released a great YouTube video about this topic.
Here are some more great resources on this subject: