My journey from Android to Flutter began with curiosity and a thirst for exploration. I started by immersing myself in articles and videos that showcased the capabilities and inner workings of this innovative framework.
One of the first resources I encountered was an official Flutter documentation tailored for developers transitioning from platforms like Android, iOS, or web development. This guide proved to be a fantastic starting point, providing a comprehensive overview of how Flutter approaches concepts familiar to Android developers. It established parallels between the two platforms, enabling me to grasp the equivalent solutions in Flutter and quickly familiarize myself with its libraries and the Dart language.
Optimizing Flutter UIs: Understanding the Widget Tree
One of the most interesting things that I learned was how Flutter renders Widgets. The way they use a system consisting of three trees - Widget, Element, and RenderObject, each of them with a separate role - in order to optimize when a screen is redrawn seemed fascinating. By knowing how widgets are rendered, it improved the way I was building the UI and how I optimized the logic behind updating certain widgets on the screen.
Dart: A Familiar Feel for Kotlin Devs
Next up was learning the Dart language. Dart is a programming language developed by Google that is derived from Java and JavaScript. Despite its influences, I found out that Dart has several similarities with Kotlin:
- Null safety: Both Dart and Kotlin prioritize null safety. They have built-in features that help prevent null pointer exceptions, reducing the risk of crashes and errors in your code.
- Type inference: Like Kotlin, Dart can infer types, eliminating the need for explicit type declarations in many cases. This simplifies your code and makes it more concise.
- Modern language features: Both Dart and Kotlin come equipped with modern language features such as garbage collection, lambda expressions, string interpolation, and more. These features enhance productivity and make coding more efficient.
- Object-oriented programming (OOP) concepts: Both Dart and Kotlin support object-oriented programming (OOP) paradigms like classes, objects, inheritance, and polymorphism.
However, one minor drawback of Dart compared to Kotlin that I noticed is that it has fewer built-in properties for strings and collections. For example, if you need to perform certain operations or manipulate strings and collections in specific ways, you may need to implement the necessary properties and methods from scratch or find them in a library.
Beyond MVVM: Exploring Flutter's State Management Options
My Flutter journey culminated with a study on how to develop a state management architecture. In the context of Android development, the task of choosing an appropriate project architecture is relatively straightforward. The official documentation advocates for the Model-View-ViewModel (MVVM) pattern, providing a practical illustration of its implementation.
However, in the realm of Flutter, the landscape of solutions for managing state is considerably more diverse, with options like BLoC, Riverpod, and others. Initially, choosing the right approach can be confusing, especially when comparing the efficiency of different options. To find the most suitable solution, it is beneficial to create the same application with varying architectures and compare them to determine which one aligns best with your specific requirements.
Building for Both: Mastering Platform-Specific Tweaks in Flutter
Transitioning from developing for Android to adopting a cross-platform framework like Flutter brings both exciting opportunities and unique challenges. One of the most intriguing aspects of this journey is learning to fine-tune applications for both Android and iOS, each with its distinct environment and requirements.
iOS Initiation: An Android Developer's First Impressions
As an Android developer embarking on a Flutter learning journey, venturing into the unfamiliar territory of the iOS environment was an exciting challenge. My initial steps involved familiarizing myself with the basics, including testing on devices and simulators. A key difference I encountered was that the iOS simulator only mimics the software environment, while Android emulators mimic both software and hardware. This distinction became apparent when working with certain features like notifications and payment systems, where physical devices were necessary for accurate results.
Moreover, there were subtle differences in how each platform increments version numbers during build creation. Understanding these nuances was crucial to maintain version sync between platforms.
Adapting to iOS-Specific Features
Certain features, such as location, payment systems, and notifications, required extra research and consideration. While I had a grasp of their functionality on Android, their iOS counterparts posed new challenges. For instance, I needed to learn how subscription bundles appear when fetched in code and the proper setup for a testing account to verify payments. Mastering these aspects was imperative, especially in the context of potential client interviews, as it instilled confidence in our team's capabilities.
Does Flutter Measure Up? Performance vs. Native Apps
When it comes to cross-platform app development, there's always the question of performance compared to native apps. Flutter is a popular cross-platform framework that has gained a reputation for its ease of use and attractive UI. But how does it stack up in terms of performance?
Thanks to the new rendering engine Impeller, which is the default on iOS, there has been a significant increase in the performance of Flutter apps. Impeller is designed to address early-onset jank issues and enable smoother animations. It achieves this by compiling all shaders and reflections offline at build time, building all pipeline state objects upfront, and controlling caching explicitly.
What is Impeller?
Impeller is a new rendering runtime for Flutter. It is designed as a replacement for Skia, with the goal of enabling better animations and addressing early-onset jank issues. Impeller is able to do this by compiling all shaders and reflection offline at build time. It builds all pipeline state objects upfront and controls caching and caches explicitly.
In addition to its performance benefits, Impeller has several other objectives:
- Instrumentable: It tags and labels all graphics resources, such as textures and buffers. It can capture and persist animations to disk without affecting per-frame rendering performance.
- Portable: Flutter doesn't tie Impeller to a specific client-rendering API. You can author shaders once and convert them to backend-specific formats, as necessary.
- Leverages modern graphics APIs: Impeller uses, but doesn't depend on, features available in modern APIs like Metal (used for iOS) and Vulkan (used for Android).
- Leverages concurrency: Impeller can distribute single-frame workloads across multiple threads, if necessary.
Impeller on Android
Unfortunately, Impeller is not yet available on Android. It is currently in preview, and we will have to wait until we see this improvement on Android as well. However, even with the current engine Skia, Flutter offers promising results in terms of performance.
Taking all these new improvements that Impeller provides, we can safely assume that Impeller has the potential to make Flutter apps even more performant. This is especially important for complex apps with intensive graphics or animations.
Overall, Flutter's performance is constantly improving, thanks to advancements like Impeller. While it may not be as performant as native apps in all cases, the gap is narrowing, and Flutter is a viable option for many types of apps.
Faster, Leaner, Happier: Flutter's Impact on Development
When working with Flutter, one difference that I noticed compared to native projects is the reduced team size. This provides several advantages that considerably enhance development efficiency.
- Streamlined Decision-Making: With a smaller team, decisions regarding design, API endpoint structure, and feature complexity become more straightforward. This simplifies the decision-making process, leading to faster resolution of issues and accelerated feature development.
- Immediate Feature Availability: A key benefit of Flutter is that once a feature is completed, it's accessible on both Android and iOS platforms immediately. The elimination of separate development and testing for each platform ensures consistent feature availability across all platforms.
- Efficient Estimations: Flutter speeds up estimations since they are done once for the Flutter platform rather than separately for each native platform. This saves time and effort.
Flutter's development is further streamlined by two key features: Hot Reload and DevTools.
- Hot Reload: This feature allows developers to make code changes and see the results almost immediately without restarting the app. It works by injecting updated source code into the running Dart VM, which rebuilds the widget tree automatically. This significantly accelerates the UI development process, as developers can iterate on changes quickly and see the results in real time.
- DevTools: This set of tools helps in debugging and analyzing Flutter project performance. It includes sections for inspecting UI layout and state, checking memory usage, diagnosing UI jank issues, and CPU and network profiling. DevTools aids developers in identifying and fixing performance issues, resulting in a smoother and more responsive app.
From MVP to Full-Scale Apps: The Power of Flutter
In summary, Flutter's combination of faster development times, leaner teams, and efficient tools makes it an ideal choice for MVP (Minimum Viable Product) projects. It enables developers to build and iterate on ideas swiftly without compromising quality or platform compatibility. This has led to Flutter's growing popularity among startups and enterprises alike, valuing its ability to deliver high-quality apps with reduced time and resources.
As projects evolve and expand, Flutter continues to prove its value in scaling applications. Its flexibility and robustness enable developers to effortlessly transition from initial prototypes to fully-fledged, feature-rich apps. The streamlined development process and seamless platform compatibility provided by Flutter make it a compelling solution for projects of any size. Whether it's a small startup or a large enterprise, Flutter has the capability to meet the demands of scaling projects without sacrificing performance or user experience.
Ready to build your product with Flutter?
Let's StartIulia Maria Bîrsan
Flutter Developer