By Josephus Paye II • Published Dec 28, 2022, written in June 2022 • Back to Home
In Picking a framework for an iOS and Android app in 2022, I outlined some considerations for picking a cross-platform framework for building mobile apps, and did a survey of the major options available in 2022. This post continues where that left off, with a closer look at Flutter and why I think it’s a good bet at this time.
Flutter is a cross-platform UI framework that provides a custom declarative rendering framework on top of Skia, the 2D graphics library used by Android, Chrome, and Firefox. You write apps in Dart, a very nice and ergonomic JS-like language that gets compiled to native code when you build for production.
The following is a loose list of things that I find compelling about Flutter, roughly categorized.
Flutter has a layered architecture that allows for building on or swapping out parts of the system. This may seem like a implementation detail, but its implications are actually profound. The layered architecture allows for
Flutter implements most of the system in Dart, with a thin layer of C/C++ code. This provides great control, inspection, and debuggability over the system. Together with shipping the Flutter source repo as the installation method, this is very useful (”A defining characteristic of Flutter is that you can drill down into the source for any widget and examine it.”). You can press F12 at anytime and view the source (and documentation) of any of the framework APIs under use.
Apps run in a Dart VM during development: for stateful hot reload and incremental re-compiles. For release apps are compiled to native machine code (x64 or ARM) or JS when targeting the web.
The docs are really good. For example, see Flutter architectural overview. Sometimes example code in the docs include references to Hamilton lyrics, which is a big plus in my book.
There are some great teachers and explainers in the community.
The space of things to learn seems large, but the concepts that underlie them are relatively small and consistent. Consider this description of composition in the framework:
Where possible, the number of design concepts is kept to a minimum while allowing the total vocabulary to be large. For example, in the widgets layer, Flutter uses the same core concept (a
Widget
) to represent drawing to the screen, layout (positioning and sizing), user interactivity, state management, theming, animations, and navigation. In the animation layer, a pair of concepts,Animation
s andTween
s, cover most of the design space. In the rendering layer,RenderObject
s are used to describe layout, painting, hit testing, and accessibility. In each of these cases, the corresponding vocabulary ends up being large: there are hundreds of widgets and render objects, and dozens of animation and tween types. The class hierarchy is deliberately shallow and broad to maximize the possible number of combinations, focusing on small, composable widgets that each do one thing well. Core features are abstract, with even basic features like padding and alignment being implemented as separate components rather than being built into the core. (This also contrasts with more traditional APIs where features like padding are built in to the common core of every layout component.) So, for example, to center a widget, rather than adjusting a notionalAlign
property, you wrap it in aCenter
widget.
From a learning experience point of view, this translates to being daunting at first, due to the sheer number of different things to know about or consider. But such a system provides non-linearly increasing benefits as you learn more and more of the framework, starting from the abstract concepts and features at the core, and building up to bigger and bigger abstractions. This idea of a “shallow and broad” API reminds me of Tailwind CSS, where such an approach is largely a success.
Many of the core developers of Flutter have domain expertise in the problem of building good UI frameworks. They also seem to be quite good communicators. Additionally, it seems many of the high-level decision making people (the public facing ones at least) are still intimately involved with the code. A few examples I could find: