Winter has arrived in the Northern hemisphere, with yellow leaves and temperatures falling with the wind. The last stable version of Flutter of the year has quietly arrived in front of you. Say hello to Flutter 2.8

The update included the hard work of 207 contributors and 178 reviewers, all of whom produced 2,424 PR posts and closed 2,976 issues. Special thanks to one of the most prominent community contributors to this release: Bartosz Selwesiuk, VGV’s Flutter development engineer, who submitted 23 PR for the Camera plugin for the Web platform.

All of this resulted in a very significant performance improvement for both the Flutter engine and DevTools, Also included are the stable release of the Google Mobile AD SDK for Flutter, a series of new features and optimizations for Firebase, Flutter WebView 3.0, and the new Flutter Favorite Package, a big step towards a stable version on the desktop, and a new version of DartPad that supports more packages. Let’s take a look!

Performance improvement

The primary goal of Flutter is to maintain its quality as always. We spend a lot of time ensuring that Flutter works smoothly and stably on a variety of devices.

Application startup performance

This update optimizes application startup latency. We tested on GPay applications with more than a million lines of code to make sure the changes worked on the actual production application. The changes cut the startup time for GPay by about 50% on low-end Android devices and by about 10% on high-end devices.

We have also made some improvements to Flutter’s GC strategy for calling the Dart VM to avoid inappropriate GC during application startup. For example, Flutter notifies the Dart VM of memory pressure only when TRIM_LEVEL_RUNNING_CRITYCAL and signals higher than that are present before rendering the first frame on an Android device. In local testing, the initial frame interval on low-end Android devices was reduced by about 300ms at most.

In previous versions of Flutter, the platform thread was blocked when creating a PlatformView out of caution. After careful reasoning and testing, we removed some of the serialization steps, reducing GPay’s startup time on low-end devices by at least 100ms.

There has long been an artificial delay in initializing the default font manager before initializing the first Dart ISOLATE. Since it was the primary delay bottleneck, delaying the initialization of the default font manager to run at the same time as the first Dart ISOLATE reduced startup latency and made all of the above startup optimizations more noticeable.

The application memory

Because Flutter loads the Dart VM’s service ISOLATE as quickly as possible and loads it into memory along with the AOT code bound to the application, this can make it difficult for Flutter developers to track memory metrics on some devices with limited memory. With Flutter 2.8, the Dart VM service isolate on Android devices has been split into separate bundles that can be loaded separately, reducing memory usage by around 40MB prior to load. The Dart VM’s ability to send notifications to the operating system about the memory usage of an AOT program is now supported by a file that does not require multiple reads, reducing subsequent memory usage by about 10%. Therefore, memory that previously held copies of file data can be reclaimed and used for other purposes.

Performance analysis

In some cases, developers want to see Flutter and Android tracking events at the same time, or in production mode to better understand application performance issues. To meet this requirement, Flutter 2.8 now has the option to send performance tracking events to the Android event logger upon application launch, even in production mode.

In addition, some developers want more performance tracking information about raster caching behavior to reduce lag in animation effects, which allows Flutter to quickly reuse expensive, reusable images rather than redraw them. New stream events in performance tracing allow developers to track the life cycle of raster cached images.

Flutter Developer Tools

For debugging performance issues, the new version of DevTools has added a new “enhanced trace” feature to help developers diagnose UI bottlenecks caused by costly build, layout, and drawing operations.

With either trace enabled, the timeline shows events for Widget building, RenderObject layout, and RenderObject drawing, as appropriate.

In addition, the new version of the developer tool also adds support for analyzing application startup performance. This configuration file contains CPU samples from Dart VM initialization to the first frame of Flutter rendering. After you press the “Profile app Start up” button and load the app startup Profile, you will see the “AppStartUp” TAB selected for the Profile. You can also load the app launch profile by selecting this user tag filter (if present) from the list of available user tags. Selecting this TAB will display your app’s startup profile data.

PlatformView for Web Platform

This release also includes performance optimizations for the Flutter Web view, not only for Android and iOS platforms. The platform view is the medium through which a Flutter is embedded into the UI component from the host platform. Flutter Web implements this functionality using the HtmlElementView Widget, which allows you to embed HTML elements in your Flutter Web application. If you are using the Web version of the Google_maps_FLUTTER plugin or the Video_Player plugin, or if you are following the Recommendations of the Flutter team on how to optimize the display of images on the Web, you are already using platform view.

In previous versions of Flutter, the embedded platform view created a new canvas, adding a new canvas for each embedded platform view. Creating additional Canvases is a very performance-intensive operation, because each canvas is the same size as the entire window. In Flutter 2.8, the canvas created for the previous platform view will be reused. So instead of having 60 times the cost per second over the lifetime of your application, you have the cost of just one build. This means that you can have multiple HtmlElementView instances in your Web application without compromising performance, while also reducing scroll lag when using platform views.

ecological

Flutter is more than just frameworks, engines and tools — there are over 2W Flutter compatible packages and plugins available on Pub. dev, and more every day. A lot of the daily operations of Flutter developers are also part of the larger ecosystem, so let’s take a look at what has changed in the Flutter ecosystem since the last release.

Google ads for Flutter ads

First and foremost, the Google Mobile SDK for Flutter was released in November. This release supports 5 Ad formats, integrates AdMob and Ad Manager support, and includes a beta version of a new transit feature to help you optimize your Ad presentation. For more information about integrating Google Ads into the Flutter app and other monetization options, check out the page on the Flutter website.

3.0 the WebView

Another new version that comes with Flutter this time is version 3.0 of the Webview_FLUTTER plugin. We raised the major release number because of the increase in the number of new features, but also because the way Web views work on Android may have changed significantly. Hybrid Composition was available in previous versions of WebView_FLUTTER, but not by default. It now fixes many of the problems with running in virtual display mode by default. Based on user feedback and our problem tracking, we decided it was time to make Hybrid Composition the default. In addition, webview_flutter adds some much-touted features:

  • POST and GET are supported to load content
  • Load the file or string content as HTML
  • Transparent background support
  • Set Cookies before loading content

Additionally, in version 3.0, Webview_FLUTTER provides preliminary support for a new platform: Flutter Web. There have been many requests for the ability to host Web views in Flutter Web applications, which allows developers to build mobile or Web applications using a single source code base. What does it look like to host Web views in the Flutter Web application? From a coding standpoint, it’s the same:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_web/webview_flutter_web.dart';

void main() {
  runApp(const MaterialApp(home: HomePage()));
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();

    // required while web support is in preview
    if (kIsWeb) WebView.platform = WebWebViewPlatform();
  }

  @override
  Widget build(BuildContext context) => Scaffold(
    appBar: AppBar(title: const Text('Flutter WebView example')),
    body: const WebView(initialUrl: 'https://flutter.dev'),; }Copy the code

When run on Flutter Web, it works as you expect:

Note that the current Web implementation of webview_FLUTTER has many limitations because it is built using iframe, which only supports simple URL loading and has no control over what is loaded or interacting with the loaded content. However, due to overwhelming demand, we decided to offer Webview_flutter_web as an unapproved plug-in. If you want to give it a try, add the following to your pubspec.yaml:

dependencies:
  webview_flutter: ^ 3.0.0
  webview_flutter_web: ^ 0.1.0 from # Explicitly rely on unapproved plug-ins
Copy the code

If you have any feedback about webview_FLUTTER V3.0, whether it is about the Web platform, please submit the question to the Flutter repository. Also, if you haven’t used WebView before or would like a refresher, check out the new WebView Codelab, which takes you step by step through the process of hosting Web content in the Flutter application.

Flutter Favorites project

The Flutter Ecosystem Committee held another meeting and designated the following package as the Flutter Favorite package:

  • Three custom routing packages for the new routing API (aka Navigator 2) : Beamer, Routemaster, and GO_Router;
  • Drift: A renaming of Flutter and Dart’s already powerful and popular responsive persistence libraries, built on SQLite;
  • Freezed: A Dart “language patch” that provides simple syntax for defining models, cloning objects, pattern matching, and more;
  • Dart_code_metrics: A static analysis tool to help you analyze and improve code quality;
  • And packages with nice interfaces: FLEX_COLOR_scheme, Flutter_SVG, Feedback, TOGGLE_switch, and auto_size_TEXT.

Congratulations to the authors of these packages and thank you for supporting the Flutter community through your hard work. If you are interested in nominating your Favorite Flutter package for the Flutter Favorite Awards, follow the guidelines and instructions on the Flutter Favorite Project page.

Platform-specific plug-ins

If you are a package/plug-in author, you need to declare and implement which platforms are supported. If you are building a plug-in using platform-specific native code, you can do so using the pluginClass property in the project pubspec.yaml, which specifies the native class name that provides native functionality:

flutter:
  plugin:
    platforms:
      android:
        package: com.example.hello
        pluginClass: HelloPlugin
      ios:
        pluginClass: HelloPlugin
Copy the code

However, as Dart FFI becomes more mature, it is possible to implement platform-specific functionality with 100% Dart, as the Path_PROVIDer_Windows package does. In this case, you don’t have any native classes to use, but you still want to specify that your plug-in supports only certain platforms. At this point you can use the dartPluginClass property instead:

flutter:
  plugin:
    implements: hello
    platforms:
      windows:
        dartPluginClass: HelloPluginWindows
Copy the code

With this setup, you can customize plug-ins for a particular platform even if you don’t have any native code. You must also provide classes for the Dart plugin. For more details, you can read the Dart platform implementation documentation on the Flutter documentation.

Firebase-related updates

Another important component of the Flutter ecosystem is FlutterFire, which is used by about two-thirds of Flutter applications. This stabilisation adds a number of new features that will make it easier for developers to use Firebase in Flutter:

  • All FlutterFire plug-ins have graduated from beta and “grown” into stable releases
  • DartPad is starting to support some Firebase services for easy online use and experience
  • Easier UI for building authentication and querying Firestore data in real time
  • Support for Flutter using Firestore Object/Document mapping is available in Alpha

Production quality

Almost all of The FlutterFire Plugins have been moved from beta to text stable for production use.

Android, iOS and web plugins have been converted to stable versions, Includes Analytics, Dynamic Links, In-App Messaging, Performance Monitoring, Realtime Database, Remote Config, and Maritime Installations. Some of the Firebase libraries themselves are still in beta on some platforms, so the Flutter plugin will also be in beta status, such as App Check on macOS. FlutterFire plugins like Realtime Database, Analytics, and Remote Config are already available in production, so give them a try!

Firebase initialization is simply configured in the Dart code

Because these packages are already production-quality, you can now just configure them in the Dart code and initialize Firebase.

import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart'; // generated via `flutterfire` CLI

Future<void> main() async {
  // initialize firebase across all supported platforms
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

  runApp(MyApp());
}
Copy the code

Dart file to initialize Firebase on each supported platform you choose:

static const FirebaseOptions web = FirebaseOptions(
  apiKey: 'AIzaSyCZFKryCEiKhD0JMPeq_weJguspf09h7Cg',
  appId: '1:111079797892:web:b9195888086158195ffed1',
  messagingSenderId: '111079797892',
  projectId: 'flutterfire-fun',
  authDomain: 'flutterfire-fun.firebaseapp.com',
  storageBucket: 'flutterfire-fun.appspot.com',
  measurementId: 'G-K029Y6KJDX',);Copy the code

If you want to customize data structures for each platform initialization, use the Flutterfire command line tool to do so:

The command line tool finds the unique Bundle ID in the subfolders of each platform and uses it to find and create matching Firebase project details for that particular platform. This means you won’t have to download.json files to your Android project, download.plist files to your iOS and macOS projects, and of course, cut and paste code into your Web project. In other words, no matter what platform your application initializes Firebase for, this code will do it for you. Of course, this may not be the only place to initialize code, such as when you need to create the Crashlytics debug Symbol (dSYM) in Android or iOS. But at least you can get up and running for the new Firebase project.

Use Firebase in DartPad

Since we can only initialize and use FlutterFire in Dart code, DartPad naturally supports Firebase:

Here is a demo of online chats built with Flutter and Firebase, all of which can be used directly in DartPad without installing anything. DartPad support for Firebase already includes the core API, authentication, and Firestore, and more Firebase services will be available over time.

Another support is to embed DartPad instances directly in FlutterFire documents, such as the Firestore sample page:

In this example, you’ll see the documentation for the Cloud Firestore and the code for the sample application, which can be run and edited directly from the browser without installing any software.

Firebase user interface

Most users have an authentication process, including but not limited to login via email and password or a third-party account. With Firebase Authentication, you can create a new user, authenticate your email address, reset your password, even two-step SMS Authentication, log in using your mobile phone number, and merge multiple accounts into one. To this day, developers still have to do the logic and UI themselves.

Today we’d like you to try a new package called FlutterFire_UI. This package can be used to build a basic authentication experience with a small amount of code, such as setting up login using email and Google accounts in the Firebase project:

With this configuration you can build an authentication with the following code:

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutterfire_ui/auth.dart';
import 'firebase_options.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp(
        home: AuthenticationGate(),
      );
}

class AuthenticationGate extends StatelessWidget {
  const AuthenticationGate({Key? key}) : super(key: key);

  @overrideWidget build(BuildContext context) => StreamBuilder<User? >( stream: FirebaseAuth.instance.authStateChanges(), builder: (context, snapshot) {// User is not signed in - show a sign-in screen
          if(! snapshot.hasData) {return SignInScreen(
              providerConfigs: [
                EmailProviderConfiguration(),
                GoogleProviderConfiguration(
                  clientId: 'xxxx-xxxx.apps.googleusercontent.com',)]); }return HomePage(); // show your app’s home page after login}); }Copy the code

This code will first initialize Firebase and then show that the user has not logged in and the login screen is displayed. The SigninScreen Widget is configured to log in with email and Google accounts. The firebase_Auth package is also used in the code to monitor the user’s authentication status, so once the user has logged in, you can display the rest of the application. Using this snippet, you will be able to authenticate on all Firebase supported platforms.

With some additional configuration, you can add images and custom text (see this document for details) to give you a more complete user authentication experience:

The screenshot above is for mobile authentication, but since the UI of Flutterfire_UI is designed to be responsive, on a desktop browser it would look something like this:

Users can log in directly using their email address and password, and if they choose to log in using Google Authentication, whether on mobile, Web, or desktop, they will see the usual Google authentication process. If users don’t already have an account, they can click the register button to enter the registration process. Once logged in, users will be able to verify their email, reset their password, log out and bind their social accounts. Authentication by email and password works on all platforms and supports logins with Google, Facebook and Twitter accounts, as well as Apple ids on iOS. Authentication in Flutterfire_UI supports multiple scenarios and navigation schemes as well as customization and localization options. Check out the Documentation for FlutterFire UI to learn more.

In addition, authentication is not the only Flutter UI feature supported by Flutterfire_UI. It can also show the user a scrolling list of data from a Firebase data query. This version also includes a FirestoreListView to use:

class UserListView extends StatelessWidget {
  UserListView({Key? key}) : super(key: key);

  // live Firestore query
  final usersCollection = FirebaseFirestore.instance.collection('users');

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(title: const Text('Contacts')),
        body: FirestoreListView<Map>(
          query: usersCollection,
          pageSize: 15,
          primary: true,
          padding: const EdgeInsets.all(8),
          itemBuilder: (context, snapshot) {
            final user = snapshot.data();

            return Column(
              children: [
                Row(
                  children: [
                    CircleAvatar(
                      child: Text((user['firstName']????'Unknown') [0]),),const SizedBox(width: 8),
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisAlignment: MainAxisAlignment.center,
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Text(
                          '${user['firstName']????'unknown'} '
                          '${user['lastName']????'unknown'}',
                          style: Theme.of(context).textTheme.subtitle1,
                        ),
                        Text(
                          user['number']????'unknown',
                          style: Theme.of(context).textTheme.caption,
                        ),
                      ],
                    ),
                  ],
                ),
                constDivider(), ], ); },),); }Copy the code

The actual running effect is as follows:

Or if you want to provide users with the ability to add, delete, modify, or query table data, you can use FirestoreDataTable:

class FirestoreTableStory extends StatelessWidget {
  FirestoreTableStory({Key? key}) : super(key: key);

  // live Firestore query
  final usersCollection = FirebaseFirestore.instance.collection('users');

  @override
  Widget build(BuildContext context) {
    return FirestoreDataTable(
      query: usersCollection,
      columnLabels: const {
        'firstName': Text('First name'),
        'lastName': Text('Last name'),
        'prefix': Text('Prefix'),
        'userName': Text('User name'),
        'email': Text('Email'),
        'number': Text('Phone number'),
        'streetName': Text('Street name'),
        'city': Text('City'),
        'zipCode': Text('Zip code'),
        'country': Text('Country')}); }}Copy the code

It works like this:

For more information on authentication, list views, and data tables, consult the Flutterfire_UI documentation. This package is still in preview status and more features may be added. If you have any usage questions or new feature requirements, please join us in the GitHub repo.

Firestore Object/Document Mapping (ODM)

We also released the Alpha version of Firestore Object/Document Mapping (ODM), which aims to make it easier for developers to use Firestore with type-safe, structured objects and methods. By generating code, you can model data in a type-safe way to improve the syntax for interacting with documents and collections:

@JsonSerializable(a)class Person {
  Person({required this.name, required this.age});

  final String name;
  final int age;
}

@CollectionThe < Person > () '/ persons'final personsRef = PersonCollectionReference();
Copy the code

With these types, you can perform type-safe queries:

personsRef.whereName(isEqualTo: 'Bob');
personsRef.whereAge(isGreaterThan: 42);
Copy the code

The ODM also supports strongly typed subcollections and has built-in, optimized widgets to recreate its select functionality, which you can read about in the Firestore ODM documentation. Since this is still an Alpha release, please give us feedback in the GitHub repo as much as possible.

Desktop Platform Update

Flutter 2.8 is another big step towards becoming a stable version for Windows, macOS, and Linux. Our target quality standards are high, including internationalization and localization support, such as the new Chinese input method support, Korean input method support, and the recently merged Kanji (Japanese) input method support. Or, as we are tightly building support for Windows accessibility. For Flutter, it is not enough to “run” on the desktop of a stable channel; it must run well on devices of different abilities and languages around the world. We’re not where we want to be yet, but there’s a future!

One example is that we reconfigured the architecture of Flutter to handle keyboard events to allow synchronous responses. This enables the widget to handle the keystroke and intercept its passing through the rest of the widget tree. We landed on this work with Flutter 2.5 and fixed many issues with Flutter 2.8. This complements the ongoing work of redesigning how we handle device-specific keyboard input and reconstructing the way Flutter handles text editing, all of which are necessary for such input-intensive desktop applications with keyboards.

In addition, we are continuing to extend the definition of visual density to Flutter, exposing the Settings for dialog box alignment so that developers can achieve a more desktop UI friendly.

Finally, the Flutter team is not the only one working hard on the Flutter Desktop. Canonical’s desktop team, for example, is working with Invertase to develop the most popular Plugin for Flutter Firebase on Linux and Windows.

You can read more about the preview on the Invertase blog.

DartPad

The release of this new version of Flutter would not be complete without tool improvements. We will highlight DartPad’s improvements, the biggest of which is support for more packages. In fact, there are currently 23 packages available for import. In addition to several Firebase services, the list includes popular packages such as Bloc, Characters, Collection, Google_Fonts, and Flutter_riverpod. The DartPad team continues to add new packages, so if you want to see which packages are currently supported, you can click the info icon in the lower right corner.

If you want to learn about our plans to add new packages to DartPad in the future, check out this article on the Dart Wiki. There is another new DartPad feature that is also very handy. Until now, DartPad was always running the latest stable version. In the new version, you can use the new Channel menu in the status bar to switch to using the latest Beta Channel version as well as the previous stable version (which we call the “old Channel “old Channel).

This is useful if you are writing a blog post and the latest stable version is still very popular.

Removing the Dev channel

The release “channel” (aka channel) of a Flutter determines how quickly the Flutter framework and engine will change on your development machine, with stable representing the fewest changes and master representing the most. Due to limited resources, we have decided to stop updating the dev channel in the near future. While we did receive some questions about the Dev channel, we found that less than 3% of Flutter developers use the dev channel, and as a result, we have decided to officially discontinue the Dev channel shortly.

Because few developers use the Dev channel, the Flutter engineers still spend a lot of time and effort maintaining it. If you basically only use the Flutter version of stable channel (which over 90% of Flutter owners do), this change will not affect your daily development. By giving up maintaining this channel, developers can have one less channel choice decision to make, and the Flutter team can spend their time and energy on other things. You can use the flutter channel command to decide which channel you want. Here are the Flutter team’s plans for each channel:

  • Stable channels: Represents the highest quality build we have. They are released quarterly (roughly) with hot fixes for critical issues in the middle. This is the “slow” channel: safe, mature, long-term service;
  • Beta channel: An alternative to quick adjustments for developers used to a faster pace. It is currently released monthly and will be released after stability testing. This is a “fast” channel if we finddevChannels compared tobetaChannels have special needs and needs whilebetaChannels can’t be satisfied, we may changebetaThe channel’s plans to meet (e.g., speed up the release pace or reduce the level of testing and hot fixes we perform on the channel);
  • Master channel: it is our active development channel. We don’t provide support for this channel, but we run a comprehensive set of unit tests against it. This is the right channel for contributors or senior developers who are happy with an unstable build. On this channel, we run fast and break things (and then fix them quickly).

When we deactivate the Dev channel in the coming months, please consider using the Beta or Master channel, depending on your tolerance for change and the balance between using “latest” and “best”.

Breaking Changes

As always, we strive to reduce the number of disruptive changes in each release. In this release, Flutter 2.8 has no major changes other than deprecated apis that have expired and were removed in accordance with our disruptive change policy.

  • 90292Remove obsoleteautovalidate
  • 90293Remove obsoleteFloatingHeaderSnapConfiguration.vsync
  • 90294Remove obsoleteAndroidViewController.id
  • 90295Remove obsoleteBottomNavigationBarItem.title
  • 90296 Removes obsolete text input formatting classes

If you are still using these apis and want to learn how to migrate code, you can read the migration guide on the Flutter documentation website. As always, many thanks to the community for contributing test cases to help us identify these disruptive changes.

conclusion

As we close 2021 and look ahead to 2022, the Flutter team would like to thank the entire Flutter community for their work and support. Sure, we are building Flutter for more and more developers around the world, but we wouldn’t be able to maintain and build Flutter without you and every developer. The Flutter community is different. Thank you for everything you do!