Mobile apps are fun to build. I’ve explored building apps for iOS using Objective-C and Swift and I’ve also built apps using Java for Android. While both platforms and technologies have advantages and disadvantages, it’s frustrating building the same application twice for both platforms, especially if you’re a single developer. When Microsoft acquired Xamarin I immediately saw a tremendous improvement in opportunities and tooling around Xamarin. Many enterprise developers will feel right at home working in Xamarin because of C# and
XAML. I started going down that path too until I saw Flutter.
Flutter seemed to solve many of the rough edges I faced when working with other mobile technologies:
- Good IDE support with Android Studio (my preferred IDE for Flutter development)
- Good support for Visual Studio Code
- An active plugin ecosystem
- Robust widget libraries for iOS and Material Design
- Native performance on iOS and Android
- Familiar programming language in Dart
- The possibility to build Flutter apps and extend them to work on the Web with project Hummingbird, as well as native applications for desktop operating systems like Windows, Linux and Mac OS with Flutter Desktop Embedding.
To get familiar with Flutter, I decided to build a registration application. I copied the registration page design from the MeetUp app and built a clone in Flutter. Below is the process I used to build the app. The exercise was designed to be a learning experience so you may have a better way to build such an app.
Here is the current MeetUp app registration design:
MeetUp Registration Page Design
The goal is to replicate this design and build a fully functional registration experience. I imported all the packages I need in pubspec.yaml. The third party packages I used are:
The next step is to create the registration page view and layout the widgets:
With Flutter’s Hot Reload feature, iterating on the design is really fast. No need to wait for your app to completely rebuild to see your changes on the screen. This is a game changing feature and well worth the time to learn Flutter.
Registration Page Screenshot
Because Flutter’s UI is composed of widgets, if you don’t put thought into how to structure your code, your code becomes difficult to read. Each UI widget is separated into functions that can be called from the build widget. The folder structure of the application is designed to support separation of concerns. There is a folder for Blocs, Models, Screens, Services and Widgets.
To create a similar profile picture experience as the MeetUp app, I created a custom profile picture widget. With Flutter, it’s easy to create custom widgets. As per good coding conventions, I broke out the construction of the UI from the image selection. I used a Bottom Sheet Widget to give the user the option of taking a picture with the device camera or choosing a photo from the gallery.
Flutter has multiple ways to handle state. The simplest way is using setState(). There is also InheritedWidget and Scoped Model, Redux, BLoC/Rx and MobX. setState() gets really complicated for larger applications. InheritedWidget and Scoped Model are “easy” to understand if you want a bit more manageability of state in larger applications. In the future I’ll create an app and blog about how to use InheritedWidget and Scoped Model for state management in Flutter. I don’t have experience with Redux or MobX. I selected RxDart for this example app because RxDart is the recommended way of handling state by the Flutter team.
The first step to using RxDart is to include the package in your pubspec.yaml. The next step I take is to create a Bloc class. In my Bloc class I create a dispose() function to clean up the Behavior Subjects that will be created. The next step is to create a Provider class which will facilitate other widgets in my application to access the Bloc state.
In app.dart, I wrap the MaterialApp widget in the Provider. This ensures that all children of the MaterialApp will have access to the application state.
Making An API Call
Dart as a programming language has Named constructors. In my Registration Model I created a Named constructor to deserialize JSON Strings to Registration objects. I also created a toJson() function to send serialized objects to the backend API. The Register API class uses the http package to send the object to the backend and receives the returned response. In the Bloc class, the registerUser() function is used to make the API call when the form has been filled out.
For the backend API I used a C# Azure Function, run.csx. Azure Functions make it easy to wire up a mobile backend. There is so much you can do with Azure Functions so I might leave the details for another blog post.
Server-side Dart isn’t as prevalent as other server-side technologies like Node.js/Express or PHP/Laravel or ASPNET Core. My one wish when building my Flutter app is that I could build the entire front-end and back-end using Dart. I know there are server-side Dart frameworks like Angel and Aqueduct but the performance and community around those frameworks make me question if I should invest my time using them for production apps. If anyone has experience building production backend apps in Aqueduct or Angel, please leave a comment below.
The code for the application is in my GitHub repository. If this post was helpful to you or you think I can make improvements, please leave a comment below.