https://betterprogramming.pub/flutter-failed-to-solve-the-biggest-challenge-for-our-cross-platform-app-c551afa0ef18?gi=87b1ac51ba0b Get started Open in app Better Programming Sign in Get started Follow 200K Followers * ArchiveWrite For UsSupport Us About Get started Open in app Flutter Failed To Solve the Biggest Challenge for Our Cross-Platform App Harsh lessons learned from migrating a native iOS app to Flutter Georg von der Howen Georg von der Howen Feb 8, 2021*9 min read a solved Rubik's cube Photo by Olav Ahrens Rotne on Unsplash My first endeavor into mobile app development started about ten years ago. I had just bought my first iPhone (a 3GS) and I was curious about creating apps for this fascinating little device. The app that I wanted to develop at that time was (and still is) basically an ebook on steroids. It has around 50 chapters of informational content and aims to assist its audience in certain emergencies. So the main goal of the app is to present its content in a way that the user can quickly and reliably find what they are looking for in a stressful situation. I started the project initially as a web app using the jQTouch library wrapped into a native PhoneGap container deployed on iOS. Right after launch, the app made it onto Apple's recommended app list in the medical category for a week, so it looked like the app did hit a nerve. Four years later I rewrote the app as a native app in Swift before I decided to port it to Flutter in September of 2020. Here is what I learned on the last leg of the journey. Flutter: The Holy Grail for Cross-Platform Apps? When the decision was made to finally create an Android version of the app, the obvious question was how. A native Android port? Cross-platform? With Ionic and React or Vue.js? Or the new, cool kid on the block, Flutter? After some research into the current state of multiplatform app development, there seemed to be quite a lot of hype about the latter. And from the articles that were suggested by the Medium algorithms, I got the impression that people were generally quite happy with Google's project and that Flutter seemed to have matured enough to be a serious alternative. So I decided to give it a go. Surprisingly enough my initial experiences were just as great as those hailed in the articles. Believe it or not, but without any prior knowledge of Dart and the UI design principles of Flutter (coming from iOS Swift and Xcode Interface Designer) I had my app up and running on Android and iOS with Flutter within one week -- well, almost. When it got down to testing, I randomly started to see some very strange behavior: In the app, I show a spinner while a chapter of the ebook is loading. Once it is loaded and rendered in a WebView, I replace the spinner with the rendered content. Simple, actually. This worked 99% of the time, but at random times the app would get stuck on the spinner -- obviously a no-go for an app that should help you in an emergency. It took about a day or two to find out that this was caused by Flutter's HttpServer that crashed on iOS if the user briefly switched to another app and then back to mine. Bummer. I filed an extensive bug report -- but no fix on the way anytime soon. As I could not ship my app in that state, I started to look for alternative approaches. Instead of serving my ebook content via the HttpServer, I decided to copy the content from the app bundle into the app's document directory on the first app start and then open the HTML directly in the WebView using the file:// schema. After some tests and refactoring, this seemed to be a viable workaround -- until some links in the ebook stopped working on a real iOS device. Strangely, everything on Android and even in the iOS simulator worked fine. Turns out I found another bug, this time in the Flutter WebView package, that I filed and that also was quickly acknowledged, reproduced, and triaged by the team. But both bugs still exist in Flutter as of today (February 2021). By the time I had worked around that last bug, I had spent the same time hunting down and reporting bugs in Flutter that I had spent on learning Dart and porting my app. Dependency Hell The Flutter HttpServer and WebView are the two most important dependencies of my app. Without one or the other, my app will simply not work in that environment. From my experiences with iOS and CocoaPods, these days I look at every dependency as a technical debt: You borrow someone's code or functionality, and one day you might have to pay for that. Any piece of code that is not your own and that your app depends on adds to the technical debt of your app. Personally, I consider WebView and HttpServer to be core parts of the Flutter technology stack as they are both developed and supported directly by the Flutter team and not some third party. (I will spare you the gruesome details of when I experimented with a third-party WebView for Flutter as an alternative.) Therefore I was quite surprised that they seemingly received so little love from the Flutter team. I guess that either the current team at Google is just not big enough to pull off a project like Flutter (8,230 open issues as of today) or their priorities lie elsewhere. But it did inspire me to look at the dependencies of my Flutter app in general and compare them to the native Swift version of my app. Here's the gist: Native iOS (Swift) * AEXML * FontAwesome.swift AEXML was needed to parse some XHTML files as the native iOS SDK does not provide a DOM parser. The second library allowed me to use the popular FontAwesome icons in my app. Flutter * cupertino_icons * HTTP * provider * shared_preferences * font_awesome_flutter * xml2json * path * path_provider * mime * flutter_web_browser * webview_flutter * url_launcher * geolocator * geocoding * map_launcher * wakelock * device_info * package_info * scrollable_positioned_list * in_app_review * share OMG! What do I need so many packages in Flutter for? Well, being an app and not an ebook, I had added some additional features and services to my native app: an online search for professionals in the area using a third-party API, displaying some information about the user's current location using geolocation and reverse geocoding to help guide emergency services, and a speed dial for emergency phone numbers. Each feature needed some specific function from the native platform SDK -- like geolocation, geocoding, triggering a call, or preventing sleep mode while the app was open. On top of that, you have basic functionality that you will find in any decent app: asking the user for a review on occasion, allow to share content with other apps, launch URLs, open a map app at a specific location, or access some information about the local device and operating system. While iOS and Android provide most of these functionalities in their native SDKs out of the box, cross-platform solutions have to provide a bridge, package, or plug-in for every single one of them. And in the case of Flutter, they have to be implemented in three languages each: Dart, Swift/Objective-C, and Java/Kotlin. Your Flutter app will depend on countless external libraries to allow you to offer the same functionality as a native app. The functionality of your app, therefore, depends on many unknown parties with different agendas, time constraints, and motivations for development. The technical debt of your app will increase with each plug-in that you use. Cross-Platform Adds Complexity If you aim for the least technical debt, you have to write 100% of your app code yourself and use only native SDKs to provide access to the underlying hardware. Each third-party library will add to your technical debt, so at least chose carefully if you cannot implement the functionality yourself. When I started testing my native iOS app, I initially discovered a huge memory leak. So where did that come from? After understanding the concept of fantastical retain cycles and how to find them, I finally discovered the culprit: The third-party XML library was leaking in a recursion. And as I was frequently parsing XHTML with it, my app became a memory hog. Fortunately, I could find the bug in the library with my Swift skills, fix it within a day and even submit a patch to the owner of the repository. But I could find and fix it only because the library and my app were written in the same language, and this was a language that I was familiar with. So if a third party library is open source and written in the same language as your app, you might be able to live with that debt quite well. But every cross-platform solution will add multiple layers of complexity to your app and introduce additional points of failure on each layer. Any Flutter package can fail in its Dart code, Swift/Objective-C code, or Java/Kotlin code. Any update of Flutter, Dart, iOS, or Android can break parts of that package, and with it your app on one or all platforms. Unless you are fluent in all three languages and proficient on all supported platforms, you probably cannot or do not want to find and fix these problems. Note: Just as I am writing this, I receive the second support request from a user running my app on an iPhone 6 with iOS 12.4. They report that chapters are not loading on their device. In my iOS simulator with the same hardware/OS combination, everything works fine. Seriously: How on earth should I debug this if I don't own an old iPhone 6? And even if I manage to find the bug in the iOS part of the Flutter WebView plug-in, I am neither proficient in Objective-C nor do I want to spend any more time trying to fix something that IMHO should just work -- or that is declared to be still in alpha or beta state! Who Do You Want To Rely On? The added complexity of Flutter packages would not be so grave if there was a strong organization behind the project that feels responsible for providing bridges to all major native SDK functions to Dart. But most of this crucial part is excluded from the core Flutter project and left to be handled by volunteers. Their commitment and quality of work range from a stellar job to losing interest after version 0.1. If you rely on a package from a dedicated pro, good for you. If you depend on the latter, you will have to pay your debt. All you really want from Flutter is to write your app in Dart and deploy it on iOS and Android. And you have been led to believe that using this cross-platform solution will allow you to do that while saving you time and money compared to alternative approaches. In theory, Flutter (and other cross-platform solutions) can do that. Or speaking with Gartner: Flutter's vision seems relatively complete to me (even though Dart still has a long way to go to be anywhere near Swift). But Flutter's ability to execute still leaves a lot to be desired -- especially on iOS. Is this due to a bias towards Android? Or do they just lack the experience? I don't know. But what I do know is that this is where Flutter fails as a cross-platform development environment. If a cross-platform solution cannot reliably deliver commonly used app features equally on all supported platforms, it forfeits its advantages over native apps and will lose developer loyalty in the long run. From the little that I can see from the outside, I seriously doubt that Google will succeed in making developing with Flutter as seamless an experience as developing for native. If they do aim for this, they will need to put a lot more effort and manpower into the project. That again requires a lot of money, a strong commitment to the project, and a clear vision for the future. Maybe I just got unlucky and the only two faulty packages in the Flutter universe happened to be my major dependencies. But when reading through the open issues on GitHub, I somehow doubt that. And looking at the technical debt that the Flutter port of my app accumulated, I do pray for all fellow developers who already jumped on the Flutter train that Google will up their efforts instead of losing interest one day and letting the project die. I for myself am intrigued to find out if Ionic would do it better. Because at least on paper they face very similar challenges regarding technical debt as Flutter. But that would mean rewriting my app once again. If I ever do, I will let you know how it went. Georg von der Howen IT journalist, chief editor and entrepreneur who quit the rat race after 20 years. Georg now develops mobile apps and just rediscovers his love for writing. Follow 3.8K 54 Thanks to Anupam Chugh. 3.8K 3.8K 54 * Programming * Flutter * iOS * Android * Mobile More from Better Programming Follow Advice for programmers. Here's why you should subscribe: https:// bit.ly/bp-subscribe Read more from Better Programming More From Medium Convert a Python Script into an executable Ndamulelo Nemakhavhani [1] [1] Five efficient ways to destroy your tech project Lukasz Raczylo in ITNEXT [0] [0] 2D Spaceship Thrust Control in Unity Part Three Bradley Yachimowski [1] [1] Guzzle XML request and response Alexander Tarkhov [1] [1] Here's What's New In Qiskit 0.20 Qiskit in Qiskit [1] [1] How Our Team Pivoted From Java to Kotlin in 5 Steps Christian Broomfield in FREE NOW Blog [1] [1] DartLang Fundamentals #1 Kendi J. [1] [1] Android UI/UX Tips & Tricks Gaurav in MindOrks [0] [0]