Flutter is an incredible framework for building mobile apps, from its elegant declarative syntax, the flexibility and power of its widget system, the possibility of seeing the changes in the code reflected in the app in less than a second thanks to the hot reload, its portability to multiple platforms... I could go on listing its advantages, but frankly, at this point I'm sure that anyone who has been interested in Flutter or has worked with it already knows about it. However nothing comes without cost in this life, and despite its countless advantages, Flutter also brings added problems with respect to other cross-platform technologies or with respect to native application development.
In this article I am going to talk about the 4 main drawbacks that I have experienced when using Flutter professionally during the last three years. If you are just starting your Flutter learning journey don't panic, you are learning a great technology that, in my opinion, its advantages are greater than its disadvantages; however every good engineer should know both the good and the bad of the technologies he/she uses to make the best decisions. Let's see what these disadvantages are:
- 🐛 Performance issues with the official AdMob plugin on Android 9 and below
- 🥶 Janky animations at app start
- 🍏 Your iOS UI is not native, and some users are going to notice it
- 🤢 Increased size of the final build compared to native programming
Performance issues with the official AdMob plugin on Android 9 and below
The official AdMob plugin presents major performance problems, especially on Android devices with versions lower than 10. All these problems were reported by many developers in the bug manager of the plugin, and in the end a mega-thread was created that collects everything and focuses on this problem. After half a year of waiting to see if anyone was able to resolve it, the thread was closed without being resolved. At the time of writing this article, no one has a good solution to fix this problem.
I have created this sample project to properly illustrate how far the problem goes. This test project consists of a scrollable list of items, and the option to show or remove a banner ad at the bottom. If you try this project on a device running Android 9 or lower, show the banner, and try scrolling, you will see the interface laggy.
To see it graphically, I have added two performance graphs taken with a Samsung Galaxy A3 (from 2017), with the application running in profile mode:
List scroll without banner:
List scroll with banner:
However, this plugin seems not to be the only one affected by this kind of problems, as this user points out here. Looking at this picture one wonders if using Flutter for your application is a good decision or not. Keep this in mind if you plan to monetize your Flutter app with AdMob.
Janky animations at app start
This performance issue was reported a long time ago, however it is still not fully resolved to this day. The issue is a noticeable delay the first time the application runs an animation, such as opening a dropdown menu, or transitioning between two screens. The cause of this problem is the fact that to carry out an animation a shader is necessary, which is a piece of code executed by the GPU, however the compilation of this code must be done individually on each device. In the case of Android, this compilation is done the first time the app runs an animation; that is, even if the app dies and is reopened, that shader will be compiled and we won't see this problem. In the case of iOS, it is a bit more serious, since the shaders will be compiled the first time an animation is executed and they will not be stored for subsequent sessions; that is, if the app dies and is reopened, it will be recompiled, and we will notice the janky animation again.
I am not going to provide much more detail about this problem, since it has been talked about and commented on a lot; but it is important to note that the Flutter team is fully aware of this and is actively working to find a solution for it as soon as possible. There is a specific page in the documentation dedicated exclusively to applying workarounds to try to mitigate this problem.
Your iOS UI is not native, and some users are going to notice it
This problem occurs especially on iOS since it is not easy to create a UI that looks native on this platform, and some users may not like it. Yes, we can use Cupertino widgets, however the current state of these widgets is not as developed as Material widgets, plus the inconvenience of having to manage the same element differently depending on the platform.
There are some packages that try to solve this problem, I specifically started using this one some time ago and I even writte an article about it, however I stopped using it since it presented me with some problems when applying changes to the UI of the app in general, such as when you want to switch between the light theme and the dark theme.
There are several ways to cover this problem and each developer must choose their own, from applying the Material style everywhere without distinction, using Material on Android and Cupertino on iOS, using plugins like the one I mentioned...
The approach that I have decided to use is none of the above solutions, in my case I have decided to use Material on all platforms, however depending on the platform I apply some changes to buttons, texts, and other interface elements.
For example, if the platform is Android and I want to use an ElevatedButton, I just add it, but if the platform is iOS I remove the shadow to make it more in line with the Human Interfaces Guidelines. All this logic is packaged in a common library that I use in all my applications, and I also take advantage of it to apply other changes that make my widgets different from the default ones.
Anyway, I do not consider this a big problem, at the end of the day an application can provide value regardless of the framework or technology used, some users may notice that your application is not native and do not like it, but many others will value more the value it provides than this detail.
Increased size of the final build compared to native programming
Flutter comes with it its own rendering engine, and this inevitably translates into an increase in the final size of the application due to its inclusion in the package that we upload to the stores. To get an idea, we must expect that the size of our application will increase by around 4-8 MBs if we decide to add a Flutter module or create a complete Flutter app. Let's see graphically how this factor affected my app Super QR Code Reader when I decided to refactor it from native to Flutter:
In this graph you can see a very sharp increase in the size of the package that went from weighing about 4.85 MB to 12.6 MB. Due to the simplicity of this application, its size was still not very big so I hardly noticed this inconvenience. It may seem like a lot to some or it may not, however in my opinion this inconvenience will be diluted over time as technology advances and as the memory of the devices increases. For example, in iOS an increase of 5 MBs is not significant, but it can be decisive for a user with an old Android device.
In the Flutter documentation we can find a specific article that talks about how to mitigate this problem, I recommend everyone who is not applying these solutions to apply them immediately, it is very easy to do and improves the quality of the final product.
After having seen all these problems, one can ask: is Flutter really worth it?, and my answer is: Of course it is! There is no perfect technology, all of them have their advantages and disadvantages. From my point of view, Flutter is the best cross-platform tool for building apps for indie developers or small startups. Its ease of use, its flexibility and the ability to export to multiple platforms with a single code base is unparalleled.
What do you think of all this? Are there any other big downsides to developing with Flutter that you've experienced that haven't been discussed?