Aller au contenu
© @FlutterLille

I had the chance to attend first edition of Flutter Connection in Paris this year, thanks to SFEIR, and I wanted to share what I learned from this day. If you couldn't attend this is the perfect place to get a sneak peek of this amazing day.
Let's get started !

Where in the world is Flutter ? Marek Kalnik

Even though Flutter has a big and growing community, everyone in France feels that Flutter is still discreet. Marek works at BAM, and they have been building apps with React Native for a few years. When Flutter 1.0 came out in 2018, they started using it. They thought it would be an immediate success, but except for a customer in Singapore, no one was hyped.

Flutter was trending on GitHub, but no one was talking about it in France. So, Marek wondered in which countries Flutter was popular. He looked on Google Trends and found out that China, Germany, and a few African countries were where Flutter was trending. But why China?

Xianyu, a company from the Alibaba group, started using Flutter really quickly and was even working on improving Flutter with Google.

In 2020, the USA and Canada were still riding the React Native wave, but Flutter was progressing elsewhere in the world. In 2021, more and more countries were looking at Flutter, but France was still a bit behind.

To conclude, Marek said that the French Flutter community needs to grow. By looking at the success of Flutter Connection this year, I'm sure we took another step forward !

© @FlutterConn

Make your codebase more maintainable using custom_lint by creating custom refactorings and lint rules — Remi Rousselet

Remi talked to us about a package he developed at Invertase. After a quick introduction, he started live coding a custom lint rule with the package custom_lint. The rule aimed to ensure that a class correctly extended another class. For example, the class Example was supposed to extend _$Example only if it had the @riverpod annotation.

Remi began by creating a local package for his lint rule, which he could later add to his dev dependencies. After creating the file for his rule, he used tools provided by custom_lint to find class definitions, check if they had the desired annotation, verify if they were extending the correct class (based on the name of the main class), and report errors in specific parts of the code.

Another cool aspect was the ability to provide quick fixes in the IDE once errors were reported. By extending from a few additional components, Remi was able to offer a code snippet for the quick fix, allowing users to instantly resolve their extends issues.

The custom_lint package can also be used to lint other files, like the pubspec.yml, by extending LintRule instead of DartLintRule.

Remi concluded by providing some tips for effective live coding, such as using VSCode user shortcuts extensively and remembering them (😂).

© @FlutterConn

Making your Flutter apps accessible Akanksha Singh

Firstly, Akanksha reminded us what accessibility is. Accessibility is the ability to access. Approximately 15% of the population lives with some form of disability.

These disabilities can include:

  • Visual impairment (blindness, low vision, color blindness, etc.)
  • Hearing impairment (deafness, hearing loss, etc.)
  • Mobility impairment (paralysis, missing limbs, etc.)
  • Cognitive impairment (dyslexia, ADHD, Alzheimer's, etc.)

Accessibility not only benefits people with disabilities but also makes apps more usable and better designed for everyone. The key aspects to consider when designing an app are perceivability, operability, understandability, and robustness.

Various options can be implemented to improve the overall user experience:

  • Visual: Using semantics, responsive widget sizes, ensuring sufficient contrast between text and background, using accessible fonts (such as Arial, Calibri, Helvetica), avoiding conveying information solely through colors, etc.
  • Hearing: Providing captions and vibrations.
  • Mobility: Supporting voice input, optimizing touch target sizes, implementing autocomplete features, enabling easy input (e.g., dropdown menus), incorporating eye control options, etc.
  • Cognitive: Using fonts suitable for individuals with dyslexia (e.g., OpenDyslexic), employing minimalistic layouts, ensuring sufficient contrast, minimizing excessive animations, etc.

Both Android and iOS offer a range of accessibility options, although emulators may have limited support. It is essential to test apps on real devices. Two tools available for evaluating and generating reports on accessibility improvements are the Accessibility Scanner (Android) and Accessibility Inspector (with XCode, for iOS). Additionally, the accessibility_tools package can be used to identify missing accessibility considerations in your widget tree.

Flutter provides several semantic widgets that can be used to describe the widget tree and enhance accessibility. These include MergeSemantics, ExcludeSemantics, IndexedSemantics, BlockSemantics, and DebugSemantics. The Flutter team has also created an accessibility release checklist available on their website.

In conclusion, Akanksha emphasized that apps should be developed with accessibility as a primary focus, as it will only bring positive enhancements to the overall user experience.

© @FlutterConn

The world of dart-only plugins Renan Araujo

Renan presented a new approach for accessing native features. Traditionally, it would require using method channels and writing platform-specific code (such as Kotlin or Swift). After explaining the different layers of an app architecture (app code → framework → engine → embedder → runner), he introduced us to dart-only plugins using FFI bindings.

To demonstrate the usage of a dart plugin with FFI bindings, he created a simple app for copying and pasting text, which required access to the clipboard. With just a few lines of dart code, he seamlessly called platform features to copy the text.

During the Q&A session, however, Renan mentioned some limitations regarding multithreading and the potential restriction from the App Store regarding dynamically loading libraries through Dart.

© @FlutterConn

Flutter on Desktop: End to End From Build to Distribution Teresa Wu

Teresa discussed how to set up and use Flutter for desktop app development. Flutter for desktop was initially mentioned in 2019 with Flutter 1.9 and later announced as stable for Windows, macOS, and Linux in 2022 with Flutter 3. Unlike React Native, which relies on community or partner contributions for platform support, Flutter natively supports various platforms. The goal was not to determine whether Flutter or React Native is superior, as it depends on the project's context.

But why choose desktop app development? Sometimes, a web application may not be the best choice. There are popular desktop apps like Spotify, Slack, and IDEs that we use every day. Desktop apps offer advantages such as offline data storage, improved performance, and access to native platform capabilities.

Depending on the targeted platform, specific tools and disk space are required. For example, macOS requires 2.8GB of disk space, while Linux requires only 600MB. To set up Flutter for desktop development, you need a machine with the respective operating system installed. The flutter doctor command guides you through the necessary installations.

It's also possible to add desktop support to an existing project using the command flutter config --enable-<macos/linux/windows>-desktop.

There are a few differences between desktop apps and other platforms. For instance, desktop apps have access to mouse events and keyboard events, allowing the creation of shortcuts. The GestureDetector works with both mouse and touch interactions.

Regarding storage, different options are available depending on the targeted platform, but the API remains the same.

During FlutterForward, it was announced that the Flutter team is working on multi-window support.

Currently, desktop app development with Flutter lacks an emulator or virtual environment like those available for mobile development. You need a machine running the target operating system. Exploring the possibility of virtual desktops or using VMs on platforms like Google Cloud could enhance the development experience. Additionally, desktop apps lack support for macOS-Aqua and Windows-Aero design systems.

You can find a working example of a desktop app built with Flutter here.

© @FlutterConn

Dart FFI With Rust Muhammed Salih Guler

After Renan's presentation on Dart-only plugins, we had another demonstration of FFI in Dart, this time with Rust. Muhammed began by providing a reminder of what a Foreign Function Interface (FFI) is. FFI enables communication between higher-level languages like Dart and lower-level languages such as C, C++, or Rust. This capability allows developers to write platform-specific code, access native libraries, and improve app performance. Given its increasing popularity, Rust was an ideal choice for this example.

With just a few lines of code, Muhammed showcased how to use a Rust function within Dart code. For more complex scenarios, he recommended using the flutter_rust_bridge library.

© @FlutterConn

Write Complex Business Logic Visually With Flutter & FlutterFlow Pooja Bhaumik

FlutterFlow is a visual builder for Flutter that allows you to create interfaces and logic in a visual and straightforward manner. The great thing about FlutterFlow is that, in the end, it generates Flutter code, meaning you're not tied to the tool.

Pooja demonstrated the features of FlutterFlow by live coding a Kahoot! application. She began by connecting her base app to Firestore to retrieve data for display. With the intuitive interface of FlutterFlow, connecting a data source and using it to display data or create conditions based on values was effortless. She then connected her app to Firebase Authentication and performed a live demo of her application. Within seconds, the app loaded in the browser without requiring an emulator.

Pooja proceeded to create action flows triggered by button clicks. For example, she responded to an authentication event by performing an insert operation in her Firestore database.

In case you encounter complex logic, FlutterFlow allows you to write custom code and integrate it directly. If you need assistance, you can even request code from OpenAI.

FlutterFlow is designed for collaboration, and it enables you to add documentation to provide additional information to other team members working on the same project.

Pooja concluded her talk by engaging the audience in playing her customized Kahoot! game, featuring funny questions.

© @FlutterConn

The Road to Dart 3 Majid Hajian

After the lunch break, the conference resumed with a fast-paced and dynamic talk about the new features in Dart 3.

Majid delved into Records, Patterns, and Pattern Matching, showcasing their usage with concrete code examples. He demonstrated how the new syntaxes could be employed effectively.

For instance, you could validate a JSON structure with the following code:

if (json case {'user': [String name, int age]}) {
  print('User $name is $age years old.');

Or create a concise switch statement like this:

var isPrimary = switch (color) { || Color.yellow || => true,
  _ => false

Overall, it provided an excellent sneak peek at the cool new features coming in Dart 3.

© @FlutterConn

Lifecycle of a RenderObject Craig Labenz

This talk was arguably the most intriguing and technical one, although it was a bit challenging to follow, especially after lunch 😅 As someone new to the Flutter world, I decided to focus on listening and understanding rather than taking detailed notes.

Craig began his talk as a continuation of his previous presentation at Flutter Vikings, which discussed the lifecycle of a Widget. In this session, he delved into the RenderObject class, a fundamental component of Flutter's rendering system. Craig provided a comprehensive explanation of the various phases in the RenderObject lifecycle, including initialization, flush (layout, paint, semantics), markNeed, hitTest, and dispose. I highly recommend checking out his conferences, as they offer valuable insights into how Flutter operates under the hood.

© @FlutterConn

Advanced Topics With WebViews Guillaume Bernos

Webviews often bring back memories of the PhoneGap era. However, they can still be useful in certain cases. Guillaume had the idea of creating an email client with Flutter, but since emails are HTML-based, the challenge was to display them correctly. Enter webviews!

Initially, Guillaume thought of converting HTML into Flutter widgets using the flutter_widget_from_html package. However, this solution had limited display capabilities, lacking the power of CSS.

Flutter provides an official package called webview_flutter, but it has limited features. Therefore, Guillaume opted for flutter_inappwebview, which supports advanced features like webRTC and service workers, and has a vibrant community.

With webviews, it is possible to create custom HTML templates with CSS and JavaScript, injecting other HTML content, such as email content. This allows for complete customization of the page's style. The templates can even include Dart variables. The package also provides a controller variable, which enables querying the page using JavaScript. This proved useful for dynamically adjusting the webview's size based on the phone screen's dimensions, ensuring a responsive design. Additionally, it is possible to invoke Flutter callbacks from within the webview using window.flutter_inappwebview.callHandler.

Guillaume shared some tips for optimizing webview loading:

  • Preload the webview by initializing the controller early in the code.
  • Use AutomaticKeepAlive to keep the webview ready for the next email.

When building an email client, editing HTML to compose emails is also essential. Guillaume used the enough_html_editor package for this purpose. Although there are several available editors, none of them particularly stood out.

© @FlutterConn

Mind Your App Footprint! 🐾⚡🌱 François Nollen & Adrien Body & Jocelyn Griselle

As we are all aware, the IT industry has a significant impact on the environment. Fortunately, there are ways to improve our apps to reduce this impact, and that's precisely what François, Adrien, and Jocelyn are doing at SNCF with the SNCF Connect app.

When developing their new app, they paid attention to several factors:

  • CPU usage (optimize thread to run on different CPU)
  • FPS
  • Correct usage of consuming hardware (release it when you don’t use it)
  • Network usage (use cache)
  • Storage (size of the assets)

One important decision they made was to default to a dark mode theme. They discovered that dark mode consumes less energy, especially on AMOLED screens, which resulted in saving 7T of CO2 emissions.

To ensure a responsive UI, they recommend keeping the main thread for simple UI and logic, while offloading more CPU-intensive tasks to isolates using the Isolate class. To prevent unnecessary repaints of the entire app, they used the RepaintBoundary widget to isolate specific widgets and prevent repaint triggers elsewhere. Staying up to date with Flutter's advancements, such as the new rendering engine Impeller, helps improve FPS and CPU usage on iOS. The SNCF team also offloaded presentation logic, such as formatting and localization, to their BFF to reduce computation on the app itself.

For web development, they recommend deferred loading, which allows for dynamically loading JavaScript files only when needed. Using const whenever possible improves tree shaking.

In addition, they have developed an eco-mode feature to save energy when the battery is low or on when the app runs on older/low-end devices. They have even created their own package to detect such devices (which may be open-sourced in the future 👀). When enabled, the eco-mode reduces animations, blending effects, shadows, and uses more caching while reducing geolocation precision, among other optimizations. The eco-mode has resulted in increased FPS rates and significantly reduced CPU usage on older/low-end devices. They used the Flashlight tool to compare the app's performance with and without the eco-mode.

Considering backward compatibility is also important. The average lifespan of a smartphone is around 2.5 years, but by improving backward compatibility, devices can be used for a longer duration, reducing the environmental impact of producing new devices.

© @FlutterConn

From Network Failures to Offline Success: A Journey of Visible App Dominik Roszkowski

Dominik shared his experience of building a network-first app and the challenges they faced when scaling from a few users to 100k sessions.

Initially, they released the first version of their app without anticipating the level of success it would achieve. As a result, their infrastructure was not adequately prepared to handle the increased load. They started noticing numerous errors on their monitoring tool, most of which were likely network failures that overshadowed more critical issues.

One significant source of network failure they identified was when users opened the app from a notification but didn't have an immediate internet connection. This led to Firebase token refreshing failures and GraphQL subscription failures. They had been overly optimistic about the effectiveness of retry and timeout mechanisms. Additionally, some users still had 3G or low network connectivity. It was a reminder that assumptions about everyone having the same network speed as the development team's testing environment were incorrect.

In order to address the network failures, they decided to reevaluate their app and make it offline-first. They realized that their app could function without any network connectivity and only required synchronization at certain points to retrieve and save data. To simplify the implementation, they chose to replicate the model of the backend database directly in the app using SQLite, with a few adjustments. This approach allowed them to maintain data in the appropriate format and sync it with the remote database when a network connection was available. They used the drift package to work with SQLite in their app.

After reworking the app, they observed a significant improvement in fluidity, as all the loading screens were eliminated. This not only enhanced the user experience but also resolved most of the network-related problems and reduced the noise on their monitoring tools. Additionally, it led to a substantial reduction in bandwidth usage.

In conclusion, Dominik recommended a talk by Yonatan Levin titled "Offline" is not an error.

© @FlutterConn

An introduction to game development with Flame Lukas Klingsbo

To conclude the day, there was an introduction to game development with Flutter and Flame. So, what exactly is Flame?

Flame is the most popular game engine for Flutter, boasting more than 7800 stars on GitHub (Dart has 9200 stars, so don't forget to give stars to Dart!) and over 160 contributors over the course of 4 years. They recently released version 1.8.0 and are already working on version 2.0.0.

According to Lukas, Flutter is well-suited for game development, despite being a high-level framework. It provides direct access to the graphical context, offers excellent rendering performance, supports multiplatform development, and benefits from a mature ecosystem.

One of the cool things about Flame is that it's just a Widget, so you can place it anywhere in the widget tree (which could be useful for hiding some Easter eggs 👀). The basic code structure for a Flame game involves creating a class that extends FlameGame and then using it with the GameWidget provided by Flame.

Like any game, Flame games rely on a game loop that includes an update method and a render method. The update method receives the delta time in microseconds since the last update and allows you to move to the next state

In Flutter, everything is a Widget, but in Flame, everything is a Component. Flame provides a wide range of components to simplify the management of sprites, sprite animations, sprite transitions, parallax effects, text, shapes, and more, making development easier.

The Flame ecosystem also includes various packages to handle sound with flame_audio or to use the Dart port of the Box2D physics engine with flame_forge2d.

Although not covered in this particular talk, Flame also offers additional notable features such as CameraComponent, collision detection, gesture/input handling, particle effects, built-in debug mode, and more.

With Flame, you have a powerful game development framework that leverages the strengths of Flutter to create engaging and interactive games.

Thanks to all the organizers for this amazing day and thanks again SFEIR for giving me the opportunity to attend FlutterConnection.

See you next year ! 🥐🐤