Things I wish I'd known when I started using Flutter
Recently, I’ve been playing around in Flutter as a way to make iOS
apps. I hate basically everything about Apple’s iOS development
environment, especially Swift, XCode, Apple’s documentation. For me,
using frameworks has been muchs easier than trying to write native iOS
code. Having tried a lot of them at this point, Flutter seems like the
current best option. However, there are definitely some things I wish I
had known when I started using Flutter.
Objects are cheap and composability is key
When I first started playing around in Flutter, I was always confused by how few properties individual widgets have. Compared to CSS for example, there wasn’t a way to define things like padding or borders in most widgets.
What I eventually realized is that Flutter just has a very different
model. Conceptually, objects are intended to be cheap in Flutter and the
primary way to build a UI is through composing widgets together. So you
don’t need to feel bad wrapping that widget in an Expanded
wrapped in a Column
wrapped in a Padding
!
Most UI components don’t store any state
Most (all?) built-in UI components in Flutter don’t store any state.
For example, the Checkbox
widget doesn’t store a
checked/unchecked value. The TextField
widget doesn’t store
the current text in the field. There’s a couple interesting things that
come from this:
- This is why the various controller classes for widgets (like
TextEditingController
) exist. The widgets themselves don’t store any state so Flutter provides the controller classes to do that. You can also choose to store the state yourself. - You must redraw widgets when their state changes. In most
UI frameworks that I have used, a checkbox has a “checked” value and if
you click the checkbox, it toggles visually. In Flutter, clicking a
checkbox does nothing by default. You have to implement the
onChanged
handler and have that cause a redraw by updating your application state. This one took me a while to wrap my head around.
Simple state management is usually best
There are a lot of libraries for state management in Flutter. After trying a lot of different options, I believe that really simple state management is the best option for most cases. What does this mean? There’s a couple built-in classes that will handle 99% of your state management needs: ValueNotifier/ChangeNotifier and ValueListenableBuilder/ ListenableBuilder.
At a high level, I do the following for widgets with state:
- Extend
StatefulWidget
- Have your
State<T>
class either implement/mixinChangeNotifier
or expose someValueNotifiers
. - Wrap the widgets that consume that state in
ValueListenableBuilder
orListenableBuilder
.
I like this because it allows me to be as granular as I want, either
by defining a bunch of small ValueNotifiers
or having the
whole state class extend ChangeNotifier
. It does the same
thing on the widget builder side, where you can wrap your entire widget
in ListenableBuilder
or just individual UI elements.
Don’t use the Cupertino library
This is just my opinion but I would recommend against using the Cupertino library. I’m mostly aiming to make iPhone apps so my first instinct was to use the Cupertino library to match the iOS look and feel. Unfortunately, the library isn’t very fleshed out. There’s a lot of functionality you would expect that is available in the Material library but not the Cupertino one.
I recommend using Material or some kind of third-party UI components.