I’ve spent the last 3 months being the sole developer for a fairly complex Flutter app for a client. It’s been very fun and Flutter is, generally, a pleasure to code with.
It’s also been a learning experience, so I’ve compiled a list of the 5 most important lessons (for me).
Split your stateful widgets
Often, we refactor classes when a file gets big, and that’s fine. But there is another reason to split a stateful widget in Flutter. Remember that the whole widget rebuilds when your code calls setState()? So split your widgets between their static and dynamic content, separate widgets if they contain 2 visual parts that obtain their data separately etc
Example: I had a stack of images, inside a list, and some of the images contained animations. With a simple logic, all the stack code fitted in under 100 LOC in one widget. However, scrolling was a bit jerky. I improved it by creating a widget for each image, and animating those as and when required, instead of rebuilding the whole stack.
You may have heard that Dart is single threaded. Coming from a Java/Android background, it can be confusing. How do you handle async code? What concept replaces Android’s AsyncTask and Java’s threads? And how do you implement a callback?
The concept is called Futures. A Future completes with either a value or an error. You use a try/catch statement to catch the error. To create a Future, you use a Completer.
This all sounds very abstract, so let’s dive into an example.
In this code tutorial, we will set up a screen with 2 separate widgets. Both widgets use the same data repository as their data source. The data repository needs to make an API call to initialise its data. While it does so, the widgets show they are waiting for the data. When the data is ready, the widgets display it.
When working with images, you often need to overlay text or icons on them. Perhaps to show the name of the image, or an icon to favourite it. In Android, the trusted android:background xml attribute does the trick. In iOS, you can add an UIImageView to the bottom of your view hierarchy. But, how can you do that in Flutter?
One of Flutter’s cornerstone widgets is Container. You often use it for positioning and size. And, it provides a decoration property, which is a decoration painted behind the child.
For this code tutorial, we will set up an app with 2 screens. The first screen will display an image, with a title at the bottom, aligned left. The second will display the same, with an additional icon in the bottom right of the image.
An overwhelming majority of Flutter code tutorials show phone screens in portrait mode. But what about tablets and landscape mode? Android comes with a system to specify layouts per orientation – can you do this with Flutter?
When I created my first Flutter app Crosswords to learn French, I locked it to portrait mode. This was fine for v1.0, but for v1.1, I wanted to add tablet support. This meant allowing landscape mode. To my surprise, it took only about 30 minutes. You read that right, 30 minutes! As I had already put each UI section into its own widget, it was easy to recombine them based on orientation. And retrieving orientation turned out to be easily done, once I knew where to look ( MediaQuery and MediaQueryData).
Note: I chose to maximise crossword size, so I decided not to show the custom keyboard view across the full width of the screen, but, technically, I could have done it just as easily.
Many Android apps require what Android deems a dangerous permission. For example using the camera, adding an event to the user calendar, or reading the user contacts. Previously, Android used to ask for those permissions at install time, but since Marshmallow, it does it at runtime. So, how do you implement the Android runtime permission flow in Flutter?
A search of Flutter plugins currently shows no results, so I had to figure it out myself for my app Preset SMSs.
In this code tutorial, we will create an app that shows a list of all contacts with a mobile phone number. The app displays a loading screen while it obtains the contacts and an error Snackbar when the app has no permission. The Android code itself is based on the official Requesting Permissions at Run Time guide. For communicating between Flutter and Android, we will use Method Channels.
Love them or hate them, ads are a common way for indie app developers to make money from their apps. So, how can you display a banner ad in your Flutter app?
If you search Flutter packages for “ad”, there are currently two relevant results, both for AdMob. One is admob and the other is firebase_admob. As of writing this, the former only supports interstitial ads and hasn’t been updated for 7 months; as for the latter, it supports interstitial, banner and rewarded video ads as of version 0.3.0, and was updated last week.
This code tutorial will show you how to display a banner ad using firebase_admob plugin. It includes a trick to make sure the ad doesn’t hide the bottom of your screen content, so, for example, your Snackbars aren’t hidden behind the banner ad.
Material Design’s Snackbars are a great way to give feedback to users, and even allow them to undo or retry an action. So, how do you display a Snackbar in Flutter?
If you create a Material App in Flutter, you will use a Scaffold. In the Scaffold.of documentation, there are examples to show a Snackbar. While very useful, in all those examples, the Snackbar is shown when the user presses a button. But often, you need to show a Snackbar following an async operation, such as a server call.
In this code tutorial, we will demonstrate how to show a snackbar outside the build method of your widget, and will call this after an async operation.
A common Android UI pattern for edit screens is to ask the user to confirm that they want to discard their changes when they tap the back button or back navigation arrow. So, how do you catch this user event in Flutter?
Well, after a fair amount of trial and error, the solution turned out to be quite simple, using a WillPopScope.
A fairly common UI action for lists in native apps is “swipe to dismiss”. That is, the user can swipe left, or right, and a leave-behind UI element indicates what will happen if the user continues on with swiping. Typically, the leave-behind element is a delete icon.
Flutter comes with a UI widget called Dismissible – as the name suggests, it enables us to implement this pattern. This code tutorial will show you how.