When talking to clients interested in native app development, the conversation often veers toward cross-platform tools. The perceived cost savings are obviously appealing, building a single codebase, rather than multiple, to target both iOS and Android.
Although the majority of my experience in mobile has been building native iOS, I’ve also worked with cross-platform tools on several commercial apps, e.g. Apache Cordova (more commonly known as PhoneGap), RubyMotion and React Native, and for some hobby apps, with Xamarin… so as Flutter gained popularity (progressing to Release Preview), I decided to take a look at the latest cross-platform offering.
So, what is Flutter exactly?
Flutter is an SDK from Google for building cross-platform (native iOS and Android) apps.
There are lots of resources out there which can guide you through building apps with flutter, some of which I’ve compiled for you here. In this post, I’d like to summarise my learnings, from spending ~48 hours building my first Flutter app.
The good bits
There are many benefits to using a tool like Flutter:
- You’re hitting two platforms not one
- Native UI performance and animations are smooth
- Hot-reload really does accelerate the development cycle, avoiding lengthy app restarts
- You don’t need to be an iOS/Android expert and can avoid a large number of platform specific concepts, e.g. Storyboards, view controllers, lifecycles (iOS) or Activities, Intents, Fragments (Android)
- Composing apps from pre-built widgets results in rapid development
- The (Material design) widgets are feature-rich, implementing common UI patterns you can re-use (e.g. sticky/stretchy headers, hero animations)
- The layout model is familiar (to web developers) and reactive paradigm to most
- Dart is easy enough to pick-up, if you’re familiar with Swift, Kotlin or Java
- Out-of-the-box support for automated unit, widget and UI tests, code coverage and linting tools, CI setup (with Travis CI) was straightforward
- Documentation is good and there’s lots of free resources available to up-skill
- Google seem heavily invested in it, e.g. using flutter internally for several apps
The (not so) good bits
There are a few limitations to be aware of when using Flutter:
Flutter renders its own UI, it doesn’t use components provided by iOS/Android SDK’s. This has its advantages. You can for instance, be more confident in the UI rendering consistently between iOS/Android, as there is no dependency on platform code.
Having said that, a couple of limitations do arise from this:
- Missing UI components, the most notable being Maps and inline Web views. We can use plugins to open native maps/web views, but these are presented in a separate view controller (iOS)/ activity (Android), which may not align with your design requirements.
- Limited number of Cupertino widgets. Probably as expected, the Material design components are far more mature than their iOS counterpart. This is an issue if you want to build an app that closely conforms to the iOS look and feel. Also, the current widget implementations aren’t pixel perfect replicas of those provided by the iOS SDK.
- When the OS updates its UI, the flutter team (or open source community) need to play catch-up. I imagine a change along the lines of when safe areas were introduced in iOS, would cause some serious changes.
- We can’t use the vast array of open source Swift/Java UI components, within the flutter canvas.
Sometimes you need to dig into platform specifics, you will need some level of understanding and experience with both iOS and Android development, for example:
- set a splash screen and app icon
- using iOS simulators and Android emulators (installing, launching, configuring, etc.)
- debug build issues
- deploy to app stores
- build your own plugins
Plugins are key gap-fillers for native features that flutter can’t offer out of the box. As Flutter gains in popularity, the number of plugins will increase, however at the time of writing, the ecosystem is not as rich as you would find with alternatives, like React Native. Plugins to consume AWS resources for instance, are lacking.
Most plugins are written by 3rd parties, as with any open source dependency, the quality varies. Also, I’ve found plugins often don’t expose the full native API or do so only for one platform (the platform which the plugin author is more familiar with).
Initially I thought the learning curve for Flutter would be pretty steep, in addition to a new programming language, you need to learn a bunch of widgets (classes) and their attributes. As it turns out, I spent ~1 day getting familiar with the core concepts and Dart basics, took about ~2 days before I felt comfortable putting together a fully-functional app (understanding which widget to use takes a fair bit of trial and error).
So full disclosure, that’s the time I spent before embarking on the ~2 days building the app in this repository.
Another factor to consider is that Dart isn’t a particularly well known language, although coming from Swift, the learning curve wasn’t that bad and I would imagine the same for anyone coming from Java/Kotlin. The perception of using a specialist language however, may be off-putting to developers.
Building apps with flutter is all code, there’s no official visual tools to help you construct UI. Hot reload helps, but you’re testing against a specific device vs being able to switch between devices at design time, as you would with Storyboards (iOS), for instance.
Tooling can also be a bit buggy, e.g. hot reloading doesn’t always work, sometimes you need to stop, delete the app then re-run, to ensure clean state … basically flutter clean is your friend.
OS Support Limitations
At the time of writing, flutter will work with iOS 8 and above, Android 4.1 and above. Widgets are responsive to layout changes, but Tablets are not officially supported.
Conclusion, should you use it?
Flutter really is an impressive piece of technology. Despite its limitations, I’m keen to learn more and would consider using Flutter for my next cross-platform project. Of course the answer to whether you should use Flutter is, “it depends”… but there are some scenarios where I feel it’s a bit more clear-cut:
- With clients open to using emerging (higher risk) technologies for potential savings
- Where budget limitations mean building pure native is not a viable option
- For internal, non customer facing apps, proof of concepts and throwaways
- For customer facing apps where the design requirements are flexible
- For teams with limited mobile app experience
- When the design requirements dictate a pure iOS look and feel
- Where maps are the primary app feature or there are embedded web view (hybrid) requirements
- For apps which require Tablet support
- For teams without any mobile app experience
- When you’re targeting a single platform