Flutter apps – starting work with the new Google cross-platform framework
Sobiesław Gabara
Paweł
Up until very recently Flutter was just another novelty, an upcoming new player in cross-platform application development. As a seasoned iOS dev, I didn’t bother to give it much thought. Few months into the release – everyone seems to be talking about it. “Everything is a widget”’ “Beautiful native apps in record time” and a few other buzz phrases seemed to give Google’s creation a pretty good marketing head start. Naturally, our company, always on top of the latest trends, jumped right at it and started working on setting up a Flutter team. Here’s a rundown of my first serious attempt at using Flutter’s DART and widget based framework.
Table of contents
First step – Installation
Setting up Flutter on MacOS is quite trivial and the official Flutter website explains the macOS install process step-by-step Being a Swift developer, I had Xcode and Xcode command line tools already on-board, which made the process even quicker.
I did have to install Android Studio (Visual Studio Code can be used as well) to be able to code with Dart – Flutter’s language. I also had to add ADB to have my connected android device(s) visible. For the IDE I decided to try out Android Studio as I used to write some “hello world” apps for Android back in the day, so regardless of changes to-date, the environment was familiar at least.
All in all, the setup took me about two hours, and I was able to create a simple demo Flutter project and run it on physical Android and IOS devices connected to my Mac via USB.
The tutorials
Flutter official website is rich with code samples for beginners, which explain how proper working with Dart should look like. My first reaction was a bit of a panic, as what I saw was very different to what I’m used to. I didn’t “feel” the code, there were no classes, methods or variables in plain sight – sure, they were there, but the syntax differed significantly from what I’m used to in Swift. If you enjoy looking into new programming languages, I suppose you know that I’m talking about – everything seemed a bit odd – a different editor, different color -coding, and obviously – a whole different language to figure out. I’m pretty sure all I need is to take Dart for a longer spin to get a more familiar feel for all the visual code.
During tutorials reading/executing I have learned how to setup views using basic Flutter widgets – for placing buttons and labels, opening next view etc. It’s all done from the code, so for now a simple way to separate view’s code from the business logic is still on my to-do list.
First Flutter app – concept
Before starting to write the project, it’s necessary to do some research on the basics. For a Flutter initiate, the amount of information to absorb is quite significant, but you are not left to fend for yourself. The fast-growing Flutter Society offers a lot of support, and wherever the official Flutter page is lacking, you can turn to git repos, bugs lists, or Stackoverflow. From the sheer amount of Flutter-related topics and issues, you can see the already huge and constantly growing interest in Flutter/Dart.
For my first project I needed to find out a bit about:
- async get/post
- login form
- user profile with history
- images processing form
- playing sounds
- showing alerts
With the help of all the aforementioned go-to places, this particular bit was a piece-of-cake.
Getting started
So much to do and think about :). Time for the next step – starting some basic project work preparations. First things first – changing the name of the project – this turned out to be not much of an effort with the straightforward instructions from Flutter’s site. Kudos go to the Flutter team here – we all know what a chore project renaming can be on different platforms, so Flutter shines here as in the framework, renaming is no big deal at all. Same goes for changing package name with plenty of info to be found online.
Few more things to consider were: Android Manifest, Info.plist in Xcode, setting bundle.using flavours, Signing, Runner.workspace. Setting deployment target for IOS, for android. Yet again, extensive community and Google’s support were super helpful.
What I thought was a bit odd in Flutter was the long import syntax:
import ‘package:flutter_demo/model/user.dart’;
I prefer short imports, best if they only include the file name. My first impression on DART was that it’s quite lengthy. Instead of describing the job in a few simple words I felt like I was telling a detailed story about an action :). I will see what changes once I see and get a good feel for Dart constructs.
Working with code – analyzing examples
As a wise person once said “Learning programming language happens in two phases – learning to read the code and then to write the code” so a good place to start is with analyzing existing samples to get a proper feel of the Flutter platform. Seeing Abstract classes were present was a relief as I knew I’ll be able to do some inheritance and protocol-like SWIFT logic.
One small detail
Your app must be displayed in forced portrait view only – easy to figure out following this link
Fabric/Crashlytics integration.
Admittedly, this is where I had to fight my first serious Flutter battle. With Fabric, we’re currently in a bit of a situation, with it bought by Google and in the middle of being integrated with Firebase Crashlytics. It was not very clear to me which packages I should be adding to handle Fabric Beta distribution and Crashlytics error reporting. A little investigation on the side on Firebase Alpha replacing Fabric Beta for build distribution shows promise, but right now, with only Beta version available, hybrid access to both Fabric and Firebase is needed.
I had to create one Firebase Project for the app, create an IOS and Android app, transfer the GoogleService-Info.plist and google-services.json to platform project’s folders, perform necessary modifications in AndroidManifest.xml, build.gradle etc for Andro add Info.plist file and AppDelegate.m for the IOS. Then only the proper import in main.dart file and main() method modification to finally make Crashlytics work.
Running Continuous Integration
All this took the larger part of the day, but in the end my Continuous Integration was fully set up for my Flutter project, with the help of the fastlane for both IOS and Android platforms. There is no way to do it for Flutter directly or to create one fastlane setup for Flutter project to handle both platforms – you have to create separate Fastfiles for each platform and set them up independently. Here is a pretty good tutorial on automating continuous building. I have modified it slightly to let the builds go to straight to Crashlytics instead of iTunes or Google Play.
Configuration of the above is a bit of a handful – my advice is to stay on top of proper package versions, as it took me a lot of time to find the reason behind the “unexpected” compile errors.
I also had to deal with this error for Android:
> java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex
This one was an easy fix after a quick search yielded the solution of adding multiDexEnabled true to defaultConfig of the build.gradle
Flutter-friendly design pattern – why BLoC?
As with any project, setting up the right architecture for running the app project is top priority. Researching both community and official recommendations, which all conclude that BLoC was the preferred option. I found this article helpful in understanding how BLoC architecture works. Turns out it’s very similar to MVVC for iOS, with the bloc class used instead of modelView. I figured BLoC architecture is the way to go and decided to work with it in my project.
The example app from the above article was quite similar to my own first flutter app project – all I needed was to add an additional project layer and separate content for particular modules. All it took was to expand basic folder list to all modules (the UI, blocks, models, resources). I also created a commonModels folder for keeping all models used in different modules in it. Some more in-depth read into the article resulted in a few slight changes to the code and refining the BLoC architecture for my project.
The implementation
Off to a rocky start, I found it really hard to create anything with DART code that would actually work – full respect to all who switch to the Flutter language with ease. For me, it was back to school on pretty much all aspects of writing code – one step forward, two steps back. All I knew was what I learned from step by step tutorials, examples, and some test debugging to see how establishing code breakpoints works.
In the end, I managed to create a small widget with 5 buttons defined by a designated model properties – not exactly enough to call in an application. Creating the UI didn’t go all that great either – all of a sudden DART, and the whole “everything is a widget” idea, started to remind JSON – just more complicated. I am still to familiarize myself with all UI parameter definitions – edges, dimensions, alignements etc… – I’m planning to get right on it once I’m done writing and analysing the code.
All in all I found working with Flutter somewhat challenging, but I can see that all the hype around is not baseless. With some refinements and in-depth learning, I think it is a very good addition to any software house’s tool set, and for myself, a great way to expand my capabilities as a programmer.
Would you like to know more about differences between cross-platform and native app development? Download our ebook! It is the ultimate guide to Cross-Platform vs Native development. You will find out more about native applications, cross-platform applications and technologies used to build them.
Read more:
Flutter vs React Native – cross-platform frameworks comparison
Top 4 technologies to develop your app in 2021