Why Flutter might be better than native Android/iOS development in 2020
A quick history of mobile app development
In mid 2007, the iOS mobile operating system was released, and in late 2008 came Android. For a very short period of time, if you wanted an app to be available on both of these platforms, you would have to develop essentially 2 different apps each with their own codebase, one app developed for Android and the other one for iOS. This is called native app development.
In no time at all, in 2009, PhoneGap, currently known as Apache Cordova, came to be and introduced the concept of Hybrid App Development, a way to develop for both Android and iOS simultaneously in one codebase, thus in theory, removing the need to have 2 separate teams to develop a business’s native apps.
This is a trend that only continued to grow each year with new companies introducing new technologies every couple of years. In 2011, we got Xamarin, and in 2015, we got Facebook’s React Native as well as Drifty Co’s Ionic. By this time, it seemed like we had quite a few different technologies to choose from if we wanted to build Hybrid Mobile Apps.
But each one of these frameworks fell short for a number of reasons. App performance was noticeably lower on Hybrid Apps built with any of these. None of them could capture the native look and feel of each platform, and it was quite difficult to get the same layout, design, and functionality to work on both platforms. Thus, to this date, native app development is still generally the preferred method if you want quality apps.
However, on December of 2018, the hybrid development framework Flutter 1.0 was released and.. It may have levelled the playing field
Flutter is a framework created by Google to revolutionise the world of hybrid app development. It runs on the Dart programming language, a language that was also created by Google and it brought forth high hopes in many developers from its very first reveal in 2015 under the codename Sky where it was shown running on Android at a consistent 120 frames per second, something nobody’s seen before in a hybrid app.
But it wasn’t just smooth performance that made Flutter a strong contender to change the mobile meta. It can also generate views that are both beautiful and consistent between both platforms, and includes a feature called Hot Reload which lets developers instantly see changes in their code without having to recompile the whole app. This is especially noticeable to Native Android Developers like me who sometimes have to wait several minutes to see changes in code.
With the engine and tools that Flutter brings to the table, it may seem like Hybrid App Development is the new way to go for mobile development in 2020.
But whether you suspect that to be the case, or you’re an avid believer in native apps, we’re putting it all to the test.
We’re going to be comparing Hybrid App Development through Flutter to Native App Development in these categories, and we’ll be comparing not only the resulting app developed by each method, but also the development process as well to see whether Hybrid App Development really is the better method in 2020.
Now I’ve personally done both Flutter and Native Android Development, but not iOS development, so for the most part, we’ll be comparing Flutter to Android. I do believe iOS should follow through with most of the same points as Android, but if you’re an iOS developer just urging to prove me wrong, feel free to do so down in the comments.
1. App Performance and Design
A hybrid app’s goal is to look and feel like a native app.
Flutter provides a host of Widgets as building blocks for your app’s layout. These do an amazing job at nailing the look and feel of Material Design components for Android, as well as Cupertino for iOS. This is to the point that you could present 2 versions of the same layout to someone, one built in Flutter and one built natively in about the same amount of time and that person wouldn’t be able to tell the difference.
And it’s already been proven from its very first reveal that Flutter apps can run at 120 frames per second on devices that can support it, otherwise at 60 frames per second by default. Generally, you don’t have to worry about performance while developing Flutter apps, unless the nature of the app you’re building is memory intensive, but in that case, native apps would be no different. So this win goes to Flutter.
2. Developer Productivity
For this category, we’ll be considering everything that goes into making the development process a quicker and smoother experience, from programming language, IDEs and other such features.
Android’s primary language is Kotlin, a huge upgrade to the previously used Java both in how clean and concise the code can be, as well as its use of powerful null and type safety. I would personally describe it as beautifully idiomatic, yet safe. As someone who’s experienced developing with both Java and Kotlin, I can say Kotlin does an amazing job in making code more maintainable and scaleable, both in how much easier it is to write clean code, as well as to prevent bugs from cropping up. I’m sure a similar case can be said about Objective-C and Swift for iOS.
Android uses the Android Studio IDE, a special version of IntelliJ IDEA tailored to Android Development created by Google, and iOS uses xCode. Both offer powerful features to develop for their respective platforms and come with a host of plugins. Android Studio especially excels in this category as it can make use of plugins built for the base version of IntelliJ IDEA.
Where Android falls short however is in its compile time. If you want to see the results of your code changes, you have to recompile your whole app again which can take anywhere from 30 seconds to several minutes, depending on the size of your app. Android Studio does cache compiled components wherever it gets the chance to make the process faster, but this can occasionally cause confusing errors in your builds, especially when you’re working with multiple git branches, and when this happens, get ready for a pain-steakingly long wait as you rebuild your project.
Flutter’s primary language is Dart, and alas, it does require semicolons which always catches me off, as I’m so used to developing in the semicolon-free land of Kotlin. Overall, I feel like Kotlin has much more to offer than Dart, but one thing I do love about Dart is the way it handles callbacks. You can simply label a function as async and suddenly, you can write asynchronous code as if they were synchronous by making use of the await keyword. In simpler terms, network calls do not require callbacks, well at least you can make it look so.
As great as it is however, I believe Kotlin’s coroutines does a better job at this. It might require a little bit more groundwork to setup, but the tradeoff is much better control of your async calls, threads, and better error-handling.
Flutter offers more flexibility in terms of IDEs. Some commonly used ones are Android Studio, IntelliJ IDEA, VS Code, and Emacs, but that list isn’t exhaustive by any means.
Where Flutter truly shines is its Hot Reload feature which allows you to see changes in your code instantly without needing to recompile the whole app. This is especially useful when building your UI. It isn’t perfect though. Code that gets executed when you start your app, i.e. in the initState method of your page doesn’t get executed again when you hot reload, and dialogs don’t instantly show changes in the code without again calling the event that shows the dialog. Still, hot reload is an amazing feature that significantly increases developer productivity with Flutter.
This puts Flutter ahead of the game in terms of coding productivity and thus, gives Flutter another point.
Don’t even bring up the Android instant switch feature. That thing’s defective.
Due to being in the ecosystem for so long, there are a huge number of libraries for Android, some of which have outright become the de facto way of performing certain tasks.
Such libraries include Retrofit for making API calls, Dagger for dependency injection, mockito for mocking classes in unit tests and so on. Such libraries have stood the test of time and grown along with the platform making them great for use in production apps. So much so, I do a top 10 of these libraries every half a year. Link to the February 2020 one down in the description.
Flutter does have a great set of libraries, and what’s even better is pub.dev exists, a central area where you can find most if not all of these plugins which Android doesn’t have.
That being said, Flutter hasn’t been around for too long and thus, doesn’t have near the number of libraries as Android and iOS, but what about the big shots? What about the libraries that do matter?
Flutter does have access to some bigger names like RxDart and the Firebase set of libraries. And while these are well developed on their own, they aren’t as stable or reliable as their native counterparts. Native apps take the win on this one.
4. Resilience and Reliability
Yes, I know we just talked about how libraries are more reliable on native apps, time built them up of course! Wouldn’t it be the same for the platform itself?
Now let’s forget about the libraries for a moment. Take developers of similar skill to develop a Flutter app and a Native App and which do you think is less prone to bugs and crashing?
Let’s go back to the languages. Kotlin enforces strong null safety and type safety, meaning that in most situations where you’re likely to encounter a null pointer exception or a class cast or any other type-related exception, you’ll fail to compile
and yes that’s a good thing
I found no such feature when coding with Dart. In fact, it seems like you have so much flexibility to the point that it’s a sin.
Yes I’m looking at you, dynamic. I can never understand what’s going on with this data type.
Trying to cast it to an actual data type like string in situations where I know it’s a string gives me a class cast exception more often than not. And the methods that do seem to work doesn’t seem to be functions that belong to the dynamic class
Like I can get a Timestamp object from Firestore, of course, Flutter fetches it as a dynamic and I just put .toDate at the end of it and it works! ToDate isn’t a native method of dynamic. It just works, and it shouldn’t! Don’t even compare dynamic to the Any class in Kotlin and Swift. They are nothing alike. Any doesn’t just give you the option to break your app without being heavily aware of what you’re doing.
The worst part about it is in another situation where the dynamic isn’t secretly a Timestamp, your app will crash… if you haven’t wrapped it in a try-catch statement at the very least.
Anyway, let’s talk about error-handling. Of course, both Flutter and Native’s can make use of try-catch statements, that’s just a thing in a lot of programming languages, c-based ones especially.
But what’s the ideal way of handling an error? Assume you have an app with a solid architecture, not necessary SOLID, could be but you know, simply a well-defined architecture yeah?
At the very least, you should have a presentation layer and a domain layer. The presentation layer is completely unaware of what goes on in the domain layer. But wherever an error happens, you want to handle it gracefully and in many cases, this means showing it to the user. Even if the error happens in the domain layer, we want the presentation layer to relay that information to the UI.
On Android, chances are you’re using either RxJava or Coroutines. In either case, you’ll have an easy time handling these errors as wherever they happen, you can delegate them back to the presentation layer and show a dialog to the user or something like that.
On Flutter on the other hand, yeah you got the same kind of error handling as RxJava if you’re using RxDart, but otherwise you’ll have to rely on callbacks, try-catch statements, or monads which are great but by no means easy to get right.
If it wasn’t clear enough from my little rant about dynamic, native apps win here.
Now we’re tied, 2 for 2 here. So here’s the tiebreaker.
Which is the better choice for a business to invest in?
The winner may involve higher costs, but exponentially higher returns. It’s native apps.
The 2 points where Flutter won over native apps are App Performance and Design, and Developer Productivity, but let’s talk about those.
It’s great that Flutter can design a UI that looks great with layouts building well on both platforms, but you don’t generally spend the greatest deal of time developing layouts as much as you would working on functionality and hunting bugs. Not to mention, Jetpack Compose and SwiftUI are changing the way layouts are built on Android and iOS and when they’re production ready, building layouts could be faster than ever.
And while Hot Reload is a great tool for dishing out code at a faster rate, the stronger resilience, reliability, and availability of plugins on native apps means that you’ll be spending less time debugging and more time dishing out code you need. The absence of bugs is everything about the quality of an app.
But Flutter isn’t very far behind in the race. In a few years time, Flutter might take over and hybrid app development might become the new norm. In any case, Flutter is still well worth paying attention to because you never know what’s gonna happen.
But for now… the winner.. is native apps.
If you liked this video, hit that like button. Subscribe for more Android and Flutter related content and I will see you.. in the next video.