Round Two with Flutter – Is it a knockout?
This is round two with Flutter. I looked at Flutter last year, but it seemed still a little early to put it to serious work. A lot has changed in the past 18 months. Has Flutter matured to the point that it can be used as a mainstream mobile development tool and will it really allow for one codebase for both Android and iOS Apps? What is the state of tooling to make a developer’s life enjoyable? Let’s find out!
Like many of my other posts, I will update as I explore and learn more.
The Bell Rings for Round Two
I originally started looking at Flutter in September 2019. At the time it seemed pretty interesting. I’ve used many cross-platform tools like PhoneGap, Ionic, AppGyver, Appcelerator, and Xamarin, but for various reasons I really didn’t see any of those as broadly usable. Flutter was the first one where I could see the potential, but I thought it needed a bit more baking in the oven.
So here we are again. I have the same MacBook Pro, but it is updated with the latest macOS (10.15.7 at the time of writing). I’m up to date with all libraries and IDE updates (Android Studio 4.02 and MS VSC 1.50.0) and will be working with Flutter 1.22.1 and Dart 2.10.1.
IDE Support Android Studio or Visual Studio Code?
Great news is – there are options! Obviously there is Android Studio, which was true last year, but MS Visual Studio Code (VSC) is not only a good option, but VSC does a few things BETTER than Android Studio (AS). For example, refactoring options in VSC are dramatically richer than in AS. For example you can place the cursor in a Column and then pick off refactoring to re-wrap the element (well a Widget really) in a surrounding Widget type. VSC will add all the code for you. Pretty slick.
Working with emulators and simulators is a bit easier in Android Studio. First of all you get automatic updates notices in Android Studio for all components. If you have already started a simulator for the command line or from within XCode, you can kickoff builds for iOS simulators right from within Android Studio. Hot reloads also work pretty flawlessly for both Android and iOS run-times, unlike last year when that was not true. You can do this in VSC as well, but in my opinion its not quite as intuitive.
I have not made up my mind which IDE is better. VSC is lighter weight in terms of system resources and I’m using it for many other frameworks and for kubernetes work too. It is nice to have one IDE for all the things I do, but since my own primary interest is with Android (I use an Android phone) I lean towards Android Studio.
When working with a highly nested structure, as you will no doubt do with even a moderate;y complex layout, VSC does a better job helping with indentations and also auto inserts comments to show where UI Widgets end. AS does something similar, but the VSC implementation is better. AS does not help with comment insertions.
VSC and AS have a “Dart DevTools” feature available from the debug console mode that provides a lot of details about your app: performance, memory consumption, and most importantly a layout inspector. Opening Dart DevTools in AS pops open a window in Chrome. Doing the same in VSC opens the window as a new panel in the IDE. I prefer the AS implementation because I can pull the Chrome window to a second monitor. Personal preference I suppose. I think that is basically the case for the IDEs –> personal preference as to which you like best.
For now I think I will be using both IDEs until I can really decide which I prefer. It is great to have two options that work well together. There of course is some need to still use XCode for some things – certificates and such for example. To use XCode for that simply navigate in your project to the iOS folder and open the Runner.xcodeproj file and adjust settings as needed. It would be nice to completely eliminate XCode.
New and Interesting in Flutter 2020
Definitely in the year since I last used Flutter, things have improved. It starts with the basic tooling being more reliable. Features in the IDEs have improved and are much more stable. Hot re-load works reliably with both iOS and Android when emulators and simulators are started manually or from within the IDE. Layout hierarchy and the consistency of Widget behavior/methods has improved quite a bit.
Dart DevTools is a huge improvement, especially the layout inspector. Layout inspector gives you a great view, similar to what you have in web tools like Chrome or Firefox developer tools. Padding, margins, alignments – this is a great tool for checking your layouts.
When using Dart tools, the performance, timeline, and a few other features require you to be running in profile or release mode. In order to do that you need to have an emulator running in 64-bit mode. Use the Android Virtual Device Manager to download an image since these are not included by default in AVD.
To run an app you need to Select Run and then Profile from the main menu… in Android Studio. Then select the main.dart file with the Flutter icon next to it. Then select “Profile” from the pop-put menu.
In Visual Studio Ccode on the main menu, go to Run and Open Configurations (aka the launch.json file). Then add a flutterMode parameter for the project and set it to profile. Then start the app. When done remove this or set it back to debug.
Flutter Tips and Tricks
Working with Flutter is fairly straightforward, but there can be all sorts of things that all of a sudden become issues. Here’s a section of tips and tricks for when things went awry with my work.
At one point the Android Virtual Device Manager (AVD) started throwing an error when I would start an emulator from Android Studio (VSC was not effected). For some reason AS cannot find the binary for AVD anymore. I fixed this issue by adding some lines to the .zshrc file (with the Catalina release I have switched over from the bash shell) and also adding ANDROID_HOME references to the path like this:
export ANDROID_HOME=/Users/$USER/Library/Android/sdk export ANDROID_SDK_ROOT=$ANDROID_HOME PATH="$PATH:$ANDROID_HOME/emulator:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools"
The full Dart DevTools package requires you to have a 64-bit virtual device installed and running. To do that, go into the AVD, create a new device, pick the phone model and hit next, then instead of selecting a recommended image, select the x86 tab, and finally pick an ABI (Android Binary Image) with an _64 in the name.
From Android Studio you can build and debug an app in the Android and iOS simulator simultaneously. Run an iOS simulator by executing “open -a simulator” from the terminal (or from the device menu in AS). Startup and Android simulator from the AVD. Then you can switch back and forth between them:
Making careful use of
const keywords is important in Flutter. In large apps ensuring that Widgets and UI elements that are stateless use
final for vars and
const for both variables and constructors can have a big benefit on overall app performance. The same is true when declaring Widgets. Having the
const keyword tells the Flutter render engine that the element will never change. In larger apps this will payoff with faster screen refreshes.
Important Flutter Resources
- Flutter Widget Catalog: master catalog of all official Flutter Widgets
- Flutter SDK Main Page: main documentation page for the Flutter SDK
- Dart and Flutter Packages: Find useful Dart and Flutter contributed packages
- DartPad: Not a Dart spuer-hero then this is the spot to test and learn Dart
- DartLang: The latest news and release updates on Dart
- Flutter on Github: really want to get your hands dirty? Go here!
- Material Design: Flutter: Docs on Material Design and Flutter
Flutter – Yeah is it really One Codebase?
There’s no doubt you can build one app for both Android and iOS, however the resulting app does not really comply with the full design specs for each platform. No – sorry not one code-base to rule them all. That’s the real truth. There are ways to minimize re-coding, but there are significant gaps. Just look at the main app class MaterialApp vs. CupertinoApp the parameters and capabilities do not match.
No doubt you can do a lot with ternary expressions to minimize re-coding, but it is a reality that you must deal with. So get used to code like this:
return Platform.isIOS ? CupertinoPageScaffold( child: body, navigationBar: appBar, ) : Scaffold( appBar: appBar, //AppBar floatingActionButton: Platform.isIOS ? Container() : FloatingActionButton( child: Icon(Icons.add), onPressed: () => _startAddNewTransaction(context), ), //End FAB body: body, );
In order to deal with the differences like the above where a Floating Action Button is normal on Android, but not on iOS.
Flutter and its underlying languages have improved dramatically over the past year. Upgrades are smooth and things don’t break. There are a slew of improvements to the Dart language itself and Flutter’s key components. I find using Flutter and Dart as quite enjoyable. There is a lot to know, but it is a fun, modern language and framework.
IDE support is excellent and there are two very robust options in MS VS Code and Android Studio. The differences between these two tools comes down to personal preference. I do not see a reason to choose so I will continue to use both. Definitely the refactoring options in VSC are superior to AS, even with the Live Templates in AS.
So – not a complete knockout, but depending on your company, maybe a TKO.