[From Android dev] Flutter looks good, but is painful. Here are my frustrations with it.
Disclaimer: I’m an Android developer, I have ~1000 stars in GitHub from projects using Kotlin and I love Kotlin. I also hate both Android and iOS UI and I’m glad Swift and Compose UI are coming soon.. eventually.
Every native Android developer loves to throw some fire at Flutter, from the fact it has currently over 7 thousand open issues in GitHub to comparisons with Adobe Flash. Well, after a lot of frustration in multi-platform development, I decided to learn it and see if it would really make my life easier. I was really tired of users complaining I don’t make apps for iOS and Flutter will soon work with the web, so you can’t beat that.
I won’t dive into Stateful/Stateless widgets or generic stuff. I will dive, instead, into the stuff you won’t see written in most places, like the screenshot above. Why should someone ever need to offer a bug-fix bounty!?
Three things you should know beforehand:
- They use the number of thumbs-up in GitHub as a way of prioritising issues.
- ‘Many’ really important issues take months (or even years) to be solved, which is really frustrating — and leads to uncomfortable situations like the screenshot above.
- You constantly need to depend on a 3rd party library with dozens of stars from someone you don’t know that might not keep maintaining but you also have no other option. It’s not like Square on Android or Google with Jetpack, there is way more community involved and no way to avoid it. When I say this, it is not like I’m against open source or libraries — I love them! But I see every day a lot of useful libraries that were last updated 4~10 months ago and I’m unsure if development stopped because it is done, if author will keep updating next time Dart is updated or what.
Install process is long..
Edit: I overreacted to this. It is long! But not hard like configuring TensorFlow on Linux without Conda. Thanks, Reddit! I improved and the corrected text is below:
I thought the first step before using Flutter was going to be really simple. Unfortunately, it is not. You need to download a zip, export the PATH to the correct place (which will only be set for the current terminal session), then call a flutter command install everything. Then you still need a few commands to install all the additional tools in order to run Flutter apps in iOS or download Android Studio for Android development. For iOS you need to use homebrew to install some additional libraries.
I’m personally in favor of the idea of installing Flutter via homebrew in a single command; there is an issue opened for this (in fact, it’s the 4th most liked one). Some unofficial scripts are available and work well, others don’t, but a lot of manual work is still involved: you can only update Flutter using flutter doctor instead of brew upgrade, changing from stable to beta basically means reinstalling it and you still need to figure out where it was installed because IntelliJ/Android Studio asks for the Dart compiler location. A recent user study showed that “completing the installation process is associated with higher user retention” and it looks this is, fortunately, going to be a bigger priority for them.
Ok, so.. after it was installed, let’s learn it. After learning the really basics you are thrown in the wild — like on Android development. I ended up paying a few bucks for “The Complete Flutter Development Bootcamp Using Dart” which was “Built in collaboration with the Google Flutter team” (also available on Udemy) and it was worth it, I highly recommend. If you are on the wall, go for it, it is good enough for simple and more advanced users.
Material Design done wrong
I’m a big fan of Material Design, I know when to correctly use headline6, subtitle1, body1 and so on.. Both Material Design Components from Android and iOS follow the official guidelines and work great. With Flutter, however, well, wow! Unbelievably, you can choose between old styles with old names (default) or new styles with old names. In the new style format, if you use body1 you are actually using body2 (and vice-versa). If you want headline5, you need to use display1. A complete mess.
I wanted to use a Bottom Sheet showing a view when collapsed, a list when extended, and the list to collapse when you scroll up. Nothing surreal, something you would find even in Google Maps or other Google apps. You can’t. Native Bottom Sheet is really limited and can’t help, Bottom Sheet from not-the-Flutter-team is better, but still can’t collapse itself when a list is on top and you scroll down.
This is hard! There is no vector drawable, PDF or Lottie support (besides a 3th party library that makes a bridge with iOS Lottie and Android Lottie). There are fonts. You need to package your custom icons in fonts. Or you can just use a font with custom icons from someone else. Feather icons for Flutter, for instance, were last updated 10 months ago or 7 months ago, but the real Feather was updated 2 months ago.
If you use SVG (which also requires a 3th party library, but the author works at Google), it loads async and works as an image. You have to do slightly more work than if it were an Icon — and there might places that only support an Icon, but it’s relatively safe. My only issue with SVG has been the async nature: it has happened to me that a widget would load before the SVG, so you get that weird nothing-then-appear-effect.
Regarding fonts, if you want the Material Design icons updated in 2018, you are in bad luck. There are the standard ones, but if you need the new ones (sharp/outline/etc) you can either download them individually and build a font, hope that someone already did this, or download them and use as SVGs.
I’ve had some issues with Text Input, and there are many issues opened (around the same quantity as other components, but since most apps will need to use a text input, those issues become more frequent or irritating). One of the most annoying for me has been how you can’t use a clear button in specific scenarios (that happen frequently) otherwise it cause what you see below. Yes, this is a personal issue, but it shows how some small things shouldn’t happen and still need to be handled.
I am a heavy user of addOnScrollListener from RecyclerView in my Android apps. A lot of apps, including Netflix, use it to hide the keyboard when someone is scrolling. This requires a lot of effort in Flutter. When you use a ListView, the list catches the drag event, so a gesture callback receives nothing. You can observe the list for changes, but it will be called when list is updated/filtered/etc, so not an option. You can also use a Listener, which retrieves when finger touched the screen, really low level. [edit: szotp was able to use dragDetails with NotificationListener and find a solution]. There is also this 3rd party library that mitigates the situation for some people (specially iOS), but it’s a different use-case.
Edit: as reported by /u/filleduchaos, there is PointerMoveEvents which provides deltas, so while a verticalDelta from GestureDetector is not be available, this can mitigate the situation since Offsets contain both vertical and horizontal components. [reddit source]
The simple act of scrolling a list feels ‘wrong’, you can see it is not native. There are people trying to make it better, there are even some integration tests to compare between both, but even on Android — and Android is open source, you can feel the difference between them. I’m not saying one is fluid, other is slow. I’m just saying they scroll differently and you can see the difference. React also scrolls differently, but it is closer to native.
There is a single way to make carousels in Flutter and it is buggy — all 3rd party libraries just wrap it. If you scroll ‘too much’, it skips an element. You can’t customize it or make something like Google Play Games because it won’t allow you. I also have an open issue on this one. I might wait a bit, unfortunately, since a bug from November was just fixed in June.
This is a big big issue that deserves its own post, but this issue from Square makes me sad and also shows you that you can’t just jump into Flutter without knowing Android or iOS. The platform is not there yet and eventually you will need to deal with other things. There is also the missing onSaveInstance and a few other stuff which are a pain. Yeah, those things work differently from different platforms and even on Android it is always changing, but I hope Flutter can deal with part of it in the future.
I am really curious to see they solving this now that Flutter is going to the web:
I’m still going to keep investing time on it and hopefully ship an app or two using it. It was really nice to make interfaces with it, even when Dart is a bit limited — and I haven’t mentioned dependency injection or those more advanced things. Even shipping an app might be hard, it took them almost a year to add support for both 32 and 64 bit in APK [correction]. Let’s hope they don’t focus too much on releasing it to the web, otherwise it will soon pass 10 thousand open issues.
This wasn’t supposed to be an article like “Flutter has issues, therefore I hate it, therefore let it burn!”. It is something like “Flutter is not perfect, the pain points are showing and growing, but if they take more care it can become what the marketing team wants it to be”. We spent years and years with a lot of nasty stuff in Android, we can survive with Flutter for now. But I really hope it improves faster than the current rhythm.
Edit: if you are reading this now, you are reading an updated version. I improved the install, icons, conclusion and other sections to be more correct. Thanks Reddit for all the feedback! This was my first development article ever and I’m still shocked by the reaction and spread — 1300 views in the first few hours!