Flutter 1.22 Announcement

Hello! I am Evgeny Saturov, Flutter TeamLead at Surf . I present the translation of the official article about the fresh Flutter 1.22 update - as usual, supplemented by my comments.



This release is one of the most remarkable for me in recent years. We are moving forward not only due to the emergence of new widgets, which will surprise no one, but also due to serious infrastructure changes, as well as operational support for new operating systems. It's only the beginning!



Drove to get acquainted with the new version of Flutter 1.22.









We are pleased to announce the latest release of Flutter with extensive support for iOS 14 and Android 11. Flutter 1.22 builds on the foundations laid down by previous releases and allows developers to create fast and beautiful user interfaces for multiple platforms from a single codebase. Our quarterly stable releases contain new features, improved performance and bug fixes.



New versions of mobile OS have been released recently. We focused on making Android 11 and iOS 14 perform well on this Flutter release.



Flutter update for iOS 14 : support for the new Xcode 12, new icons and support for App Clips - an analogue of Instant Apps for Android.



Flutter update for Android 11: added support for different types of "bangs" for displays, as well as smoother animation when calling soft keyboard.



This release comes out just two months after the release of version 1.20, but even in this short time we closed 3024 issues and froze 1944 PRs from 197 contributors.



Commentary



By the way, if you have long wanted to become a Flutter contributor, but do not know where to start, here are a couple of tips. Filter issues by the good first contribution tag : from time to time, interesting issues appear there, with which you can start your journey into open source. Also, you can implement a feature of someone's dream by filtering issues by the new feature tag . There are puzzles even for beginners. You will be able to perpetuate your name in the history of the framework - of course, if the developers of the Flutter-team agree that such a feature should be implemented.





In addition to supporting new mobile OS versions, we have other news, including a preview of one of the most requested Android features: 



  • restoration of the state, 

  • new "universe" Material of buttons, 

  • new library to support localization and internationalization, working with Hot Reload, 

  • new Navigator, 

  • stable version for Platform Views (base for Google Maps and WebView plugins),

  • a switch you can add to your code to improve scrolling on devices with high-frequency displays. 



We also have a new tool for analyzing the size of applications. In addition, developers can now create plugins for only the platforms they need by explicitly specifying target platforms in the plugin configuration.



IOS 14 target platform



Every time a new version of a mobile OS is announced, we test it thoroughly: we look for incompatibilities or changes that may affect the operation of Flutter and its tools.



In the case of iOS 14, we made some changes to Flutter to make sure it works exactly the way the developers want it:



  • Xcode 12 requires iOS 9.0 or higher, so our default template now specifies 9.0 instead of platform 8.0.

  • Flutter 1.22 fixes specific iOS 14 crashes and font rendering issues.

  • Problems with deployment to physical devices (the application did not run on a device - only on an emulator) were fixed in Flutter 1.20.4.

  • , , , Flutter Flutter 1.20.4.

  • Flutter iOS 14 ( , Flutter-).



Bottom line: if iOS 14 is the target platform for your Flutter app, we strongly recommend that you rebuild it with Flutter 1.22 and deploy it to the App Store right now to provide the best user experience for those with iOS 14.



More information including for some thoughts on Add-to-App, deep links and notifications, see the iOS 14 documentation at flutter.dev .



Separately, we would like to say about the updated support for the new iOS SF Symbols font, which inspired us to spend some time updating the cupertino_icon package . Existing use cases CupertinoIconswill automatically display in the new style as soon as you update the dependencycupertino_iconsto the new major version 1.0. If you use cupertino_icons1.0 along with Flutter 1.22, you will have access to ~ 900 new icons through the CupertinoIcons API .







For a complete list of icons, see the cupertino_icons preview page and the migration details page at flutter.dev .



Another feature you can try with Flutter on iOS 14 is App Clips. App Clips is a new feature of iOS 14: these are mini-applications weighing up to 10 MB. They give the user access to certain functions without having to download the complete application from the AppStore. Flutter version 1.22 can work with App Clips in a preliminary implementation.





App Clips on Flutter



For more information on how to create App Clips of applications using Flutter, see the documentation on flutter.dev . See also a sample simple project .



Comment



Remember Instant Apps for Android? It looks like Apple decided to bring back our 2017 and introduced a similar solution - App Clips. Moreover, you can implement App Clips even if you are writing not a native application, but a cross-platform one.



Do not forget about the limitations: if your assembly weighs more than 10 MB, then it will not work to run it in the App Clips format. In the case of a Flutter application, this can be a really urgent problem. But you will learn about this in the second half of the article: there we will tell you how you can monitor the build size of your application using a handy tool.





Android 11



This release of Flutter came out almost simultaneously with the release of Android 11. The Flutter framework and engine have been updated to support two new features introduced in the latest version of Android.



First, Flutter now takes into account the location of the bangs and cutouts on the Android phone screen, as well as the rounded edges of the screen.







Using the MediaQuery and SafeArea APIs , it is now easy to write a UI where clickable areas do not land on cutouts and rounded edges of the screen. 



The visible area of โ€‹โ€‹the application does not change size abruptly, but smoothly. The app's content will scroll in sync with the onscreen keyboard.





Pay attention to FAB



Issue # 19279- long-standing issue where on-screen keyboard show / hide animation does not sync with Flutter inset. This has been fixed for Android 11. 



Previously, there were problems due to Flutter plugins when Flutter code was inserted into a native Android application. We have rewritten the API for integrating Flutter with Android and released API v2, which is free of these shortcomings. Starting with version 1.22, we are discontinuing support for old API v1.



If you continue to use the Android v1 API, this is what it means to you:



  • New plugins are created without v1 API support.

  • The Flutter tool configuration flag has โ€”no-enable-android-embedding-v2been removed. This is the default behavior now.

  • Older apps still using API v1 will display a deprecation warning during build, which refers to the documentation for supporting new Android plugin APIs .



In the meantime, if you still have a Flutter app based on API version 1 for Android, it will continue to work. However, you may start seeing new plugins that target API v2. They cannot be used by Android API v1. For more information, see the documentation for breaking changes .







, Flutter , . 1.22 , โ€” . App Clips, ( ) , . Android, , , โ€” . .





ยซยป



The existing Flutter buttons are nice looking, but can be difficult to use , especially if you need custom themes. In addition, the Material specification has been expanded to include new buttons with new styles.



To keep up with the Material guidelines, we are introducing a new "universe" of buttons in Flutter 1.22.





New "universe" of Material design buttons



New widgets and themes have new class names. We renamed the classes in Flutter to match the Material Design specification .







The new themes follow the "normalized" pattern that Flutter recently adopted for new Material widgets. Demo version on DartPad



This is not a breaking change, because the semantics FlatButton, OutlineButton,RaisedButton, ButtonBar, ButtonBarThemeAnd ButtonThemewill not change. You can mix and match old buttons with new ones. 



New support for internationalization and localization



The core functionality you need to internationalize (i18n) and localize (l10n) your applications is available in Flutter from the start. In this release, we have added Hot reload support to update your application as new l10n information is added.







If you need more information on Flutter l10n support, including localized messages, messages with parameters, dates, numbers and currencies, read the Flutter Internationalization User Guide .



Also, if you are interested in i18n and l10n, you may need to use strings with characters that don't fit into plain old ASCII - like Unicode and emoji. The Dart team recently released the characters packagewhich helps developers work with Unicode (enhanced) grapheme clusters. This package helps solve problems such as how to properly shorten a string like "A [British flag emoji] text in English" to the first 15 characters. Using the class String, this abbreviation would be "A [British flag emoji] text in", which is only 12 characters readable by the user. On the other hand, using the package charactersgives the correct abbreviation "A [British flag emoji] text in Eng".



With this PR, Flutter uses a character pack to handle these complex characters correctly. For example, when used TextFieldwith a restriction maxLength, characters such as โ€โ€ [family of three emoji] are now correctly counted as one character. Also, with this PRthe symbol package is automatically available in Flutter projects, without the need to add it manually. Hopefully this makes it easier to work with strings of all types from all locales. To learn more about the symbol package, check out the excellent article โ€œ Proper String Manipulation in Dart โ€.



Google Maps and WebView plugins can be used in production application



On the Flutter team, we're often wary of labeling something as โ€œproduction readyโ€ until we've tested it ourselves. In the case of the google_maps_flutter and webview_flutter plugins, the main reason for the delay was in the underlying Platform Views implementation , which allows you to host native UI components of both Android and iOS in a Flutter app. In this release of Flutter, we are pleased to announce that we have hardened the infrastructure enough to declare both of these plugins ready to use.





webview_flutter plugin displaying flutter.dev



In Flutter 1.22, we added an alternative Platform Views implementation that eliminates all knownkeyboard issues and accessibility issues on Android Views . This works with Android API level 19 and higher (previously required level 20). We've also made improvements to iOS streams that make platform views more efficient and reliable (and no longer require a flag io.flutter.embedded_views_previewto be added to your iOS Info.plist).



The plugin webview_fluttersupports the new Android Platform Views mode, but currently needs to be manually enabled . When it gets more widespread in the community, we'll enable it by default.



Google Maps and WebView plugins have already benefited from improvements to Platform Views.



If you want to use Platform Views to host custom UI elements in iOS and Android, read more aboutnative Android and iOS views in Flutter app .



Commentary



Another pleasant event that does not bring any revolutionary changes to the developer's life. We have been using both of these plugins in production for a long time and have no difficulty. We hope that entering the "production ready" stage will not change this situation. We would be much more happy to see an official plug-in for Yandex MapKit support. Until that happens, all that remains is to use third-party solutions .




Navigator 2.0



If you've used navigation in your Flutter apps before , you may have noticed that the main data structure, the stack of pages the user navigates, is hidden from you. Instead, to control it, you call Navigator.pop()or Navigator.push()



Suppose you want to display a list of widgets on your home page and allow the user to click on one of them to go to the details page for that particular color.







Two screens can be implemented like this:



class ColorListScreen extends StatelessWidget {
 final List<Color> colors;
 final void Function(Color color) onTapped;
 ColorListScreen({this.colors, this.onTapped});
 
 @override
 Widget build(BuildContext context) => Scaffold(
       appBar: AppBar(title: Text('Colors')),
       body: Column(
         children: [
           // you can see and decide on every color in this list
           for (final color in colors)
             Expanded(
               child: GestureDetector(
                 child: Container(color: color),
                 onTap: () => onTapped(color),
               ),
             )
         ],
       ),
     );
}
 
class ColorScreen extends StatelessWidget {
 final Color color;
 const ColorScreen({this.color});
 
 @override
 Widget build(BuildContext context) => Scaffold(
       appBar: AppBar(title: Text('Color')),
       body: Container(color: color),
     );
}


Using the simplest style Navigator 1.0 allows you to navigate between the two screens. It looks pretty easy:



class _ColorAppState extends State<ColorApp> {
 List<Color> _colors = [Colors.red, Colors.green, Colors.blue];
 
 @override
 Widget build(BuildContext context) => MaterialApp(
       title: 'Color App',
       home: Builder(
         builder: (context) => ColorListScreen(
           colors: _colors,
           // the Navigator manages the list of pages itself; you can only push and pop
           onTapped: (color) => Navigator.push(
             context,
             MaterialPageRoute(builder: (context) => ColorScreen(color: color)),
           ),
         ),
       ),
     );
}


A call Navigator.push()is all it takes to place another page on top of the first, creating a stack of two pages. However, unlike the list of containers created in the build method ColorListScreen, this stack is hidden from you. And because it is hidden, it is difficult to manage in other scenarios, such as handling initial route deep links provided, for example, by native embedding, or a URL from the internet or an intent from Android. It is also extremely difficult to manage nested routing between different structures of the same page.



Navigator 2.0 addresses these and other problems by making the page stack visible. Here's an updated example of a transition between the same ColorListScreenand ColorScreen:



class _ColorAppState extends State<ColorApp> {
 Color _selectedColor;
 List<Color> _colors = [Colors.red, Colors.green, Colors.blue];
 
 @override
 Widget build(BuildContext context) => MaterialApp(
       title: 'Color App',
       home: Navigator(
           // you can see and decide on every page in this list
         pages: [
           MaterialPage(
             child: ColorListScreen(
               colors: _colors,
               onTapped: (color) => setState(() => _selectedColor = color),
             ),
           ),
           if (_selectedColor != null) MaterialPage(child: ColorScreen(color: _selectedColor)),
         ],
         onPopPage: (route, result) {
           if (!route.didPop(result)) return false;
           setState(() => _selectedColor = null);
           return true;
         },
       ),
     );
}


The application explicitly creates Navigatorand provides it with a list of pages representing the full stack. We create empty _selectedColorto indicate that the color has not yet been selected, so initially we do not show it ColorScreen. When the user selects a color, we call setState()as usual to tell Flutter that you want to call the method again build(), which now creates a stack at the ColorScreentop.



You update your state in the callback OnPopPage: for example, if the user is back on the screen, it means they "deselected" the current color and we no longer want to display this page.



If Navigator 2.0 looks like the rest of Flutter, it's on purpose: it's declarative, as opposed to the imperative Navigator 1.0. The idea was to combine the navigation models and the rest of Flutter while fixing a lot of bugs and adding features at the same time. In fact, this small example only scratches the surface of what's in Navigator 2.0. For details, I highly recommend the article on Declarative Navigation and Routing in Flutter .



You can continue to use Navigator 1.0: it will work the same as before. We won't be deleting it any time soon. However, we think that if you give Navigator 2.0 a try, you will love it.







. , . , , , , . .



, . โ€” Flutter. Navigator 2.0 . Remi Rousselet Twitter, . , . โ€” Surf. , , GitHub: , , , .







: Android



A new feature that you can experiment with in this release is support for state restore on Android . This is one of our most coveted features with 217 reviews!



For those unfamiliar with the need to restore state, mobile operating systems can kill applications that are in the background to free up resources for priority applications. When this happens, the OS notifies the application that it is about to "kill": the application quickly saves the state of the user interface to restore it when the user returns to the application. 



When implemented correctly, the user experience is seamless and the resources of the device are used more efficiently. Until now, Flutter did not support state recovery, and without framework support it was very difficult to get it right. Therefore, we are very pleased to provide a basic implementation of this feature for Android.



Here's a very simple example of restoring the state of the default Flutter Counter application:



class CounterState extends State<RestorableCounter> with RestorationMixin {
  @override
  String get restorationId => widget.restorationId;

  RestorableInt _counter = RestorableInt(0);

  @override
  void restoreState(RestorationBucket oldBucket) => registerForRestoration(_counter, 'count');

  void _incrementCounter() => setState(() => _counter.value++);

  @override
  Widget build(BuildContext context) => Scaffold(
      body: Center(child: Text('${_counter.value}')),
      floatingActionButton: FloatingActionButton(onPressed: _incrementCounter),
    );
}


In short, each widget gets a storage segment that is registered with RestorationMixin using a unique identifier. By using a RestorableProperty ( RestorableIntlike the one here) to store UI-specific data and registering that data with the state restore function, the data is automatically saved before Android exits the application and restored when it comes back to life. And it's all. All data stored in a type Restoration*, for example RestorableInt, RestorableStringand RestorableTextEditingController(we have several of them), will be restored. And if we haven't covered all the types you'd like to restore, you can create your own by expandingRestorableProperty.



To automatically test state recovery, we added a new restartAndRestore API to WidgetTester
. And for manual testing, the easiest is:



  • run Flutter app with state restore enabled on Android device, 

  • enable the "Don't save actions" option in Android developer settings, 

  • launch Flutter app, 

  • put it in the background,

  • return to it. 



Android will "kill" and restore your application, and you will see if everything works as you expect.







This version of state restoration is preliminary: there is still something to be done. For example, state restoration is not only a feature for Android, iOS apps can benefit from it too. We are also busy updating our own widgets to maintain their state during recovery. We have made support for classes Scrollablesuch as ListViewand SingleChildScrollView(for remembering the user's scrolling position) and TextFields(for restoring entered text), and we plan to extend it to other widgets.



True, we have not yet added a key feature - navigation support (1.0 or 2.0), which is why we call this version "preliminary". That is, the application will not open in the same place where the user was. This feature is coming soon in beta and in the next stable release of Flutter.







โ€” . Flutter- UX. โ€” , (, โ€” -), State . Restorable-, RestorationMixin.



, . : , - , , .





:



Working with our internal partners at Google, the Flutter team has made significant improvements in scrolling performance when input and display rates do not match. For example, the Pixel 4's input operates at 120Hz, and the display operates at 90Hz. This inconsistency can lead to poor scrolling performance. With the new flag, resamplingEnabledyou can solve this problem:



void main() {
  GestureBinding.instance.resamplingEnabled = true;
  run(MyApp());
}


Depending on the frequency discrepancies in question, you can see up to 97% less scrolling latency if you enable this flag. In future builds, we plan to enable this flag by default.



The new unified Dart developer tool



As always, the Flutter update concerns not only the engine and framework, but also the tools. Flutter 1.22 includes a new version of Dart (2.10) as well as a new command line tool dartthat you might find useful as well.



Historically, Dart has had many small developer tools (such as dartfmtformatting and dartanalyzercode analysis). Dart 2.10 has a unified development tool dartvery similar to the tool flutter.







Starting with the Flutter 1.22 SDK, the folder <flutter-sdk>/bin(which you probably have in PATH) contains the flutterand commands dart. For more information, see the Dart 2.10 blog post .



Application size analysis tool



Tools released as part of Flutter 1.22 include a new build size analysis utility. This tool helps you diagnose if your application size is bloating over time.



You can use this tool to collect data for analysis. Pass the flag with --analysis-sizeany of the following commands:



  • flutter build apk

  • flutter build appbundle

  • flutter build ios

  • flutter build linux

  • flutter build macos

  • flutter build windows



Using this flag when building the output artifact Flutter provides a summary of the size and composition of the artifact. It includes native code, resources, and even a package-level breakdown of the compiled Dart code.





Sample Release APK Flutter Gallery Breakdown



This summary is useful for quickly analyzing the size of a build and understanding why it is too large. In addition, the collected data is also available as a JSON file that can be viewed in the Dart DevTools, which allows you to further explore the content of your application, identify size issues, and see changes between two different JSON files by following the instructions on flutter.dev . After uploading the JSON file, you will have an interface that displays a treemap of your application's size.





An example of an APK breakdown in Dart DevTools



Documentation for the Application Size Analysis Tool on flutter.dev



Commentary



What Android Studio has been able to do by itself for a long time can now be analyzed through Dev Tools. This is even more flexible. Now you can deploy reports in Json directly to CI and monitor assembly size changes over time.



Preview: Updated Network page in DevTools



Another preliminary feature of DevTools in this release: the request body is now displayed in the Network tab .







To enable this feature, make sure you are on the Flutter dev channel via flutter channel devand flutter channel upgrade.



In addition, for applications with a large volume of network traffic, we have provided the ability to search and filter.







For documentation on the Network tab, see the Using Network View section on flutter.dev .



Hosted DevTools Inspector Tab in IntelliJ



For some time now we have been maintaining two copies of some of our Flutter tools: for example, the Inspector panel in IntelliJ and the Inspector tab in Dart DevTools. This slows down our work: we need to maintain two codebases. Also, some features are not yet part of the IntelliJ plugin - for example, Layout Explorer. To address these issues, we have enabled the ability to host the Inspector tab from Dart DevTools directly inside IntelliJ.







To enable this option, go to Preferences > Languages โ€‹โ€‹& Frameworks > Flutter > Enable embedded DevTools inspector .







, . Flutter Dev Podcast Android Studio VS Code.



, โ€ฆ . , IDE. . , Android Studio. .



Visual Studio Code



A common action that all Flutter developers face is going from the stacktrace of errors in the terminal to the location in the source code where the error occurred. In the most recent release of the Flutter extension for Visual Studio Code, these links are now parsed correctly: you can click on them and go to the desired place in the code where the crash occurred.







It sounds like a small thing, but initial feedback on this feature is already very positive.



As always, there are too many tool changelog here, but I recommend checking out the following announcements:





Customer focus: EasyA



EasyA is a subscription-based app where students engage with brilliant tutors via instant messaging. The application is written in Flutter. Apple recently flagged it as the App of the Day .







โ€œWhen schools started to switch to distance learning at the beginning of this year, we had the task of quickly launching an application to help students. Thanks to the high speed of development on Flutter, we were able to make an application for both iOS and Android. And they managed to publish them in the stores - just in time for the start of the lockdown! Under normal circumstances, this would be practically impossible. But since Flutter allows us to work with all three platforms at the same time, we were able to effectively reuse the code. Our small development team worked hard. "



Phil Kwok, co-founder of EasyA



Breaking changes



As always, we try to keep the number of breaking changes to a minimum. Here is a list from Flutter 1.22:



  • 56413 Prevent viewport.showOnScreen from scrolling the viewport if the specified Rect is already displayed .

  • 62395 [gen_l10n] Default synthetic packet generation.

  • 62588 Build routes even less.



  • The stable version of Flutter 1.22 may have come out very quickly after the 1.20 release, but there is so much good in it that we couldn't mention everything here. We hope this release helps you create awesome iOS and Android apps, and we can't wait to see what's coming to Stores! Thanks for your support: we're building Flutter for you.



All Articles