Why we chose Flutter and how it’s changed our company for the better.
An appeal to the native iOS and Android developers of the world — there is a better way.
A little background
My days of native development go back to Installer where I first developed a Podcast app. Over the past decade I’ve created dozens of applications for customers like Comcast and Associated Press. I’ve been a native developer to the core.
Over the course of my career, I’ve spent a lot of time building custom enterprise software. These experiences led me from agency/contract work to try to solve a problem… enterprise software is ridiculously hard to build, deploy, support and terrible to use. I co-founded AppTree Software and we set out to make enterprise software easier.
We set out to build a platform to make it easier for developers to build, support and deploy enterprise applications. We built mobile clients and SDKs so that your apps could inherit solutions to the complex problems of enterprise software right out of the box. Our goal being that you’d only have to worry about your specific business logic.
Taking the `native` approach
Due to the nature of enterprise software, we needed to handle hundreds of thousands of records, work offline, and be extremely secure. Naturally, we wrote our apps natively using the iOS and Android SDKs. At every turn, I rejected cross platform frameworks. They were too slow, the tooling was bad, and your UI still had to be written twice.
While native development provided the end result we needed, it was a lot overhead in both initial coding and ongoing support. To get the performance and control we needed with native app clients meant writing everything twice, hiring was difficult, and the compile times… my god the compile times (looking at you Swift). We did everything we could to make our app clients similar across the two platforms. We used Swift on iOS and Kotlin on Android. We used Realm as a cross platform data store, we used RxSwift and RxJava.
We then decided to add a third platform into the mix… the web. I set out to find a language and tooling for the our web client that met the demands of our platform and landed on Dart.
We proceeded to take all the capability in our mobile apps and build it again in Dart so our customers could run their applications in a browser.
Hitting a wall
Feature development began to drag. Now we were writing every feature three times. We had three distinct teams and as with all startups, we were trying to move very fast. Our overall productivity slowed, all of my time was spent synchronizing features and ideas across teams, architecture started to diverge, and QA time increased and quality suffered.
As part of the Dart community, we heard the rumblings of Flutter. Being a native developer for many years, I had grown a healthy skepticism towards cross platform frameworks. However, this seemed different. We loved our experience with Dart so far and the approach that the Flutter team was taking to the cross platform problem felt right.
Our excitement about Flutter grew at Google Developer Group meetup in Portland on the subject of Flutter. Coming out of the meetup, we were interested. Flutter felt like it might work for us.
I went to work that night building a presentation for myself to see where I landed on the Flutter question. By the end of this exercise, I was convinced that our company should move to Flutter. And we should do it immediately.
Here it is…
My presentation started with the cons of using something like Flutter.
Why we should not use Flutter
- New technology, APIs can change
- No built in Flutter support for things like Maps, Camera. Must use native APIs
- No support for Realm. We must rethink persistent storage.
- Not a lot of third party library support. We use Pusher, Signature Capture, Photo editing etc.
Do the above reasons matter?
- New technology, APIs can change — Not really, Google has been using internally for production, there are multiple apps in the app stores. I really only see them adding missing APIs.
- No built in Flutter support for things like Maps, Camera. Must use native APIs — No, We’ve already written these in iOS and Android. That code can be mostly re-used via a plugin. See our resulting maps plugin.
- No support for Realm. We must rethink persistent storage. — Yes, this matters and it will be a majority of our work in the re-write.
- Not a lot of third party library support. We use Pusher, Signature Capture, Photo editing etc — Similar to maps, we can write a plugin wrapper around the third party libraries so they can be used in Flutter. Which we did here, here and here.
Why Flutter: The UI Framework
- Modern API. The Flutter team has done an amazing job coming up with an API that solves our most common mobile needs all while keeping it highly customizable.
- Perfectly fits our navigation needs. Also lets us share navigation concepts across web.
- Open Source
- Reactive Views
- Modern & fast tooling
- Does it’s own rendering using Skia. It finally means that your UI and navigation can be written once and shared across iOS and Android.
Why Flutter: The development cycle
- Android Full Compile — 2:10 sec
- Android Incremental Compile — 20sec
- iOS Full Compile — 2:40 sec
- iOS Incremental Compile — 40 sec
- Flutter Full Compile — 25 seconds. On iOS, this includes building the Dart code, running
pod install, and the
xcodebuildcommand. The results are similar on Android since it uses the
- Incremental Compile — sub second thanks to the amazing hot reload.
Why Flutter: Unit testing
Android Unit Testing
- Good support. Can run on the JVM without Android if you mock Android specific classes.
- Compile time 5 sec
- Run time 1.5 sec
iOS Unit testing
- Can only run on iOS simulator. ( There are ways to get around this by moving non iOS dependent code into sub frameworks, this would have been a major re-work for us.)
- Compile time 40–2:40sec
- Run time 10 sec.
- Fantastic support. Easy to specify which tests can run on VM.
- Sub second compile time
- Runtime 1 sec.
But of course the greatest benefit is we are only writing our tests once.
Why Flutter: Code Sharing
- 95% code re-use across iOS and Android. Our own plugins being the only exception
- 60% code re-use between Flutter and Web.
- Major architecture changes only happen once, not across 3 different platforms.
- Because Flutter is it’s own UI/Widget library, we do not have to deal with implementation details of iOS & Android (ie. Android Activity, Fragments, message passing etc.)
Why Flutter: QA Testing
- Very high confidence that tests of iOS will be valid for Android & Web.
- Specific Platform QA can be limited to when native components are used
- 50% reduction in QA time
Why Flutter: Team Scalability
- Much easier to hire. We now look to take the best candidate regardless if they are from Web, iOS or Android.
- We have 3x the bandwidth now that all of our teams are consolidated on a single code base.
- Knowledge sharing is at an all time high
Giving it a go
Having sold myself on Flutter, I gave the same presentation to my CEO. He was also convinced. I then gave the presentation to the team and got everyone on the same page.
The only way to tell if this would really work for us is to try it. We set a six week deadline to see how far we could get with flutter.
Within three weeks, we had a working prototype app client. We were able to do it this quickly because of a tremendous amount of code we were able to share from our Dart web client project.
We started our Flutter rewrite in October. We will be releasing our first Flutter version into production in January.
To provide some perspective, our Android app took over a year to write after our iOS app was already done.
Not only is this because there is just a lot of code to write, but you also have to find the right people to fill out a team and then train them on the complexities of your product. No more. Now we are one team and adding a new member can be a much more incremental process.
Also, rather than splitting our talents among three distinct platforms we focused members of our team on different aspects of Flutter; UI, architecture and plugins.
Our productivity on new feature development has roughly tripled. Here’s why:
Not only do we have the obvious gains from having only one code base between iOS and Android, we are able to share ~70% (at the moment of this writing it’s 67%) of our web client code with the mobile clients. But it doesn’t end there. When we test a feature in any of the platforms, unless it’s a platform specific UI change, we are effectively testing across all three platforms at once. We did not expect this gain, but it’s real and it’s significant. We also found that because we were able to merge what was a fragmented team into one team with a common skill set, we spend less time being blocked by each other and can more easily work together. And honestly, we are happier. While it’s fun to build a new feature, it becomes a chore to then have to recreate it two more times. Then have to write the platform specific unit tests. Then QA the same thing again.
Mobile development is fun again.