In the world of mobile applications, we have two operating systems that dominate the market – Android and iOS.
Consistently, both platforms feature their native languages – Kotlin for Android and Swift for iOS. And there are two separate source codes we use to build apps that work on both Android and iOS. A common way to cope with the iOS & Android relationship is called the cross-hybrid approach. It simply means we get to use one of the given frameworks, React Native, Xamarin, or Ionic, to create one code. We compile the code and make it work on both Android and iOS.
Google found a way to make our life much easier in this department when they introduced Flutter. Flutter is a modern UI kit you can use to build intuitive native apps for mobile, web, and desktop in a flexible way.
It is a pretty powerful tool. The best part of it is, you can build native both Android and iOS apps from a single code base. Flutter is free and open-source. It has already attracted a massive devs community from all over the world.
How did our journey with Flutter begin? There was 2017, and we were about to kick off a new production project with Flutter – its current version. Although there were a few fundamental questions, we put on the table during this decision process. Can one codebase resolve the problem? Does Flutter have a lot of custom platform-specific functionalities?
Indeed, there are many cases in which Flutter, as a cross-platform framework, is a great choice. In this case, though, we would love to showcase the significant challenges we faced starting the first project with Flutter, how we handled it, and what are the lessons we learned.
The first project we made with Flutter was the Kolizja – a dedicated mobile app for collecting car collision data needed to make an insurance accident claim.
The data on the collision that is captured get compiled into a written pdf, which can be sent directly to all the parties involved. The app facilitates the process of photographing documents and recording a claim asserted on a legal basis that is required by the insurer.
Additionally, it’s easy to check the current regulations of the Highway Code and the Civil Code. The app is intuitive and simple to use. In this case, the Flutter technology worked out very well. It turned out to be a way better solution than building separate apps for Android and iOS, which would only duplicate the work.
Kolizja app has a lot of shared codebase between both platforms: iOS and Android. At the beginning of the project, we thought sharing that much of code would be a piece of cake. We even thought the entire code would be the same between both platforms.
Eventually, we ended up having two libraries written by us for the sake of this project. One of them handled each platform differently under the hood. Likewise, we had to use two separate libraries for the camera feature. The reason behind it was the cross-platform library crashed on some of the Android devices due to a bug in the current Flutter release.
Well, the great thing is Flutter is an extremely community-driven technology. There is a lot of feedback, tips, and solutions to problems you may be facing. You can easily find it.
The first of our problems was the design. We choose the ‘material design’ standard as we needed our app to be fast and efficient. We wanted it to have a modern-looking interface, so regardless of it was the iOS design library, we used it for both platforms. Such a practice might be not so common. In this case, the app was simple enough to make it happen. And hey, it was built with Flutter. Thanks to this, it looked the same on both iOS and Android platforms.
Taking most of the UX team’s expertise, we made it as intuitive and easy to use as possible.
During implementation, we went through some issues related to the architecture we picked. As our origins come from native technologies, at first, we went for so-called Reactive MVVM with no hesitation. Well, very soon, we realized it was the wrong approach. Why? Flutter is a component/widget-based framework with stateful and stateless widgets. In this case, the BLoC/Redux architectures fit much better. Later on, we started putting it into our app. We used Sqflite to handle the database connecting it with a repository pattern. Check out a separate blog post dedicated to this topic.
The other issues we faced were related to camera implementation. The camera library was pretty popular in the community. Even though, at that moment, it was continually crashing on some Android devices. As a result, we had to use different approaches for iOS and Android. Though, we made it almost painless splitting implementation between these two. Currently, this is not a problem at all, as the Flutter community has already resolved it. However, this is a good example showcasing the common issues of using a new, fresh platform.
One of the features of the Kolizja app, PDF document generation, turned out to be slightly challenging. The primary assumption of our application was to generate a large document containing tables and photos at the end of the process. At that time, the only available solution was far too basic. It required the creation of a document line by line, which would create a code that would be difficult to modify later. We wanted to prepare the easy solution that would allow us to apply multiple changes in the generated document, during the application development period and afterward. The choice of HTML as the document source was simple. It allowed the creation of a template by a person who is not directly related to the application development process.
So, we created a library that supports the conversion of pages written in HTML. It happens directly on the side of the platform at which the application is running. The whole process uses embedded document printing systems and returns the created document directly to the app itself. With this smart solution, we were able to solve the problem of document generation quickly and also provide a ready solution enclosed in a library.
Also, we have made our simple localization library to make localization features similar to the iOS ones. You can read about it in our other blog post.
During the whole development process, we went through different work phases and faced challenges of various kinds. It was either our assumption we had to adjust or a new technology that evolves, we had to learn it at each state and approach accordingly.
Some apps have to be built as native apps by default. Period. For instance, if you want to get a custom per platform view rendering or camera app – the cross-platform framework is asking for trouble. You are most likely to end up with problems you only resolve by writing platform-specific native code.
Now you might think we don’t like Flutter. It’s the opposite. We do love it!
It was a great experience to make it happen, apply such a new pattern, and, eventually, make it even better contributing to the community with our libraries.
One of the significant advantages of working with Flutter is we had so much fun creating views in a declarative way with a hot-reload feature, which is blazing fast. When we went back to our native technologies, we missed it so much.
Let’s get back to the first question – Flutter. Is it ready for production?
The answer isn’t straightforward. First of all, you have to fit the right technology to your project, and this is the only way to make it work. You can make Flutter production-ready, what’s more, it has an army of experienced developers who can help you fix any teething problems. The community around Flutter is rapidly growing. The technology itself gets better every day, as developers all over the world are contributing to get it more mature and usable.
So, it is you who have to make a decision. If you are not sure which technology to choose, we are more than happy to support you in picking the optimal solution for your project. Based on our experience, we can help you validate your idea and then adjust technology to make the whole process fast and smooth. Let’s talk.