For those of you who have had the struggle of developing apps for both Android and iOS you know the enormous pain in dealing with two code bases in two different languages (four if you count Objective-C and Java). Enter Flutter. I first learned about Flutter after considering a migration for our social music radio app from Swift to React Native and asking various friends who made the switch their thoughts. The reaction was mixed to say the least. I kept hearing about performance issues which made me nervous to make the move despite the convenience of being cross platform. One of my friends suggested I check out Flutter and ever since I’ve been hooked. I can’t say Flutter is perfect cross-platform solution but it’s close.
In the two years since I’ve learned to code I’ve built a variety of things in Python, Swift, Go, Kotlin, and now Flutter’s language called Dart and I will say Dart has quickly become my favorite language. Its syntax is readable and familiar (similar to Java & Kotlin) and runs both JIT (Just-In-Time) and AOT (Ahead-of-Time). It’s also both statically typed with all the benefits of being type-safe but also flexible enough to use a dynamic type which can contain any type at runtime. I love this feature because it gives you the speed of python for quickly coding up a feature but then the safety and performance of statically typed languages for when you’re ready for compiling to production. It’s like going back and forth between Python and Go only in the same language.
A few things to note about Flutter if you’re considering making the switch:
- Speed: This is probably the biggest advantage of Flutter. I rebuilt Chromatic’s entire social radio front end interface from scratch, alone, in just under 4 months. That’s insane considering I’ve only been a developer for 2 years. I’m not exactly a coding child prodigy over here. The same exact feature set took about a year in Swift with a developer many years my senior.
- Abstraction: The old native Swift code was around 16k lines of code. The same feature set in Flutter/Dart is now about 6k. That’s almost 1/3 of the original code doing the same thing. With Swift you have to worry about delegation, super tedious navigators, and bizarre, often non-intuitive class naming conventions. Flutter abstracts all of that away. What would take 50–100 lines of code to create table views, cells, delegates, and data sources all for a simple scrolling list view now can be done with just a handful of lines using Flutter’s Widgets. Need a hamburger menu? No problem. In one line, the Drawer widget handles it all for you and with a few ListView widgets you’re up in running in 15 minutes and a dozen lines of code.
- Cross Platform: The above would have been impressive enough if it had just replaced the native iOS code but that wasn’t all. We added an entire Android app with feature parity using the same exact code base effectively doubling the company’s addressable market size. Again all in 4 months of development.
- JIT + AOT Compilation: When you’re in development Dart runs in JIT mode which allows you to “Hot Reload” and “Hot Refresh”. This works effectively like refreshing your browser only in the simulator or on your device. If you know the pain of recompiling your app in Xcode and waiting several minutes every time you make a minor change then you know how huge this is. It honestly has made coding feel like painting or making music. Don’t like that button there? Make a change, refresh and almost instantly it is updated and live. It allows you to experiment more which overall makes building things feel more like art instead of a brute force process.
- Open Source: I found Apple’s documentation particularly frustrating so I consistently encountered roadblocks that made me utter quite a few four letter words. Because Flutter is open source, just open up the Widget or class you’re using and there’s the whole definition right there. On top of that their core SDK has some of the best documentation I’ve seen in software development.
- Community Plugins: For things that aren’t in Flutter’s core SDK, there is Pub.dev, Flutter’s community developed plugin/dependency repository. These plugins run the gamut from audio players, to vector animation widgets, to in app purchases, all of which, while new and still in development, work very well with minimal tinkering. I used the Audio Players plugin which worked perfectly for http streaming on both Android and iOS out of the box.
- Method Channel Native Communication: This was actually what made me pull the trigger to go with Flutter. When all else fails, you can use the MethodChannel widget to open a communication channel and call functions in native Android or iOS files. This process is surprisingly simple to setup so for anything that absolutely required native this prevents you from being bottlenecked by anything the Flutter SDK and the Pub.dev plugins don’t cover.
Now for the challenges:
- It is brand new: The stable 1.0 version only just released in December 2018 which as of this writing is 8 months ago. This means the community is still relatively small and the developers who know Flutter/Dart are rare. I accepted this as I think the great documentation and similarity to Java based languages make it easy enough to learn and being early in a growing language has a variety of benefits.
- Google tends to sunset products: This is something Google has built a reputation for so much so that there’s a site dedicated to it. This risk was tolerable to me because of Flutter being open source so sunsetting is in all practicality a minimal issue.
- It has feature limitations: This part was most concerning to me. I had two deal killer requirements: In app payment subscription support and an audio player that handles http streaming. Two community plugins handled these requirements with minimal hassle. There were some bugs to deal with as expected but because the plugins as well as the SDK are open source, it was fairly straightforward to diagnose the issues.
- Ambiguous Error Logs: This so far has been my biggest annoyance with Flutter. In python and many other languages the error logs point to a specific line of code where your code is failing. Not here. The error logs are ambiguous at best and downright misleading at times. As a result debugging is the most painful part of Flutter development. Break points are definitely your best friend in this department.
Overall, in my brief experience with Flutter, the hugely increased development speed, reduction in code size, open source nature and Dart’s intuitiveness make Flutter’s downsides well worth the risk for consumer focused apps.