Just days after the release of the Windows beta of Flutter on September 23, The official release of Flutter 1.22 was announced in the early hours of last night.


This update brings a new round of feature releases, performance improvements, and bug fixes. Coincizing with the release of the new version of the mobile platform (iOS 14/Android 11), this update guarantees the compatibility of Flutter on Android 11 and iOS 14. For iOS 14, this update includes the introduction of Xcode 12, Updates to the new Icon and a preview of the App Clips feature. For Android 11, the update includes a variety of screen adaptations and smooth animations for the soft keyboard.


Coming just over two months after the last release, this update is the fastest, but still has no drop in quality. Github data shows that 3,024 issues have been resolved and 1,944 PR from 197 contributors have been consolidated. Of these contributors, 114 (58%) were supported by the community, who submitted 271 PR. The largest contributor was A14N, who submitted 20 PR.


In addition to the full support for the new platform, the update to Flutter brings a lot of things to share, including the community’s most discussed Android status restoration, a new Material button component, and internationalization and localization support with hot reloading. The update also includes a new Navigator, a stable version of Platform Views (with support for Google Maps and WebView plug-ins), and improved scrolling performance on high-frequency devices, as well as a new development tool update, which you can read more about in the main article.

New platform adaptation

iOS 14

Every time a new version of the system is released on platforms such as Android/iOS, the Flutter will undergo a complete overhaul to avoid any incompatibilities. Therefore, the release of iOS 14 also prompted a new update to Flutter, which includes the following:

  • XCode 12 is only supported on iOS 9.0 and above, so the Flutter project has updated its default support from 8.0 to 9.0.

  • Flutter 1.22 fixed glitch and font rendering on iOS 14.

  • Since the Flutter 1.20.4, various problems with deployment to real machines have also been fully resolved.

  • An issue that caused the Flutter application to pop up an error notification when an application accessed its clipboard was also addressed in 1.20.4.

  • There is a restriction on iOS 14 that prohibits running debug applications on the device (except during the actual development debugging process).

  • For Internet security reasons, the locally debug Flutter application will now display a one-time confirmation dialog on iOS 14 (during development only).

If your Flutter application needs to run on iOS 14, we strongly recommend that you update the Flutter version to 1.22 and deploy it to the App Store immediately to ensure the best possible experience for your iOS 14 users.

For more information on how Flutter fits into iOS 14, including how to add to native apps, deep linking, and more, see the iOS 14 documentation on the official website.

Our goal has always been for developers to get away from all the tools and SDK updates and focus on the business logic of the app itself, which requires us to fully support the new features of iOS 14.

We have made a series of updates to the Cupertino_icon library. Now we just need to update cupertino_icon to the latest version 1.0. With Flutter 1.22, CupertinoIcons have been added an additional 900 new ICONS.

Readers can see the full list of ICONS on the Cupertino_Icons preview page, as well as the migration details page.

Another feature that developers can try out with Flutter on iOS 14 is the App Clips. This is a new feature that allows for fast, install-free opening of lightweight apps up to 10MB. After version 1.22, We can try the App Clip feature that Flutter supports on iOS.

Flutter App Clip

See the official documentation for more detailed information on how to build App Clips with Flutter, or refer to this simple example project.

Android 11

The update to Flutter also coincides with the release of Android 11 this month. Both the Flutter framework layer and engine layer have been updated to support the two new features introduced in Android 11. First, the Flutter now supports a variety of new Android screen adaptations, as shown below:

By using the MediaQuery and SafeArea components, developers can ensure that the displayed UI and interactive components are placed in a barrier-free area of the device display. In addition, we need to avoid using gesture detectors at the edge of the waterfall screen as much as possible at the moment, because these gesture detectors can cause accidental touches.

Second, the animations that show the software keyboard have been synchronized with Android 11.

There was a problem with Flutter #19279 where the display/hide animation on the system keyboard was not synchronized with the Flutter. This issue has been fixed in this update.

Comments on the Android embedded API. Last year, a new API for the Flutter plugin was released for Flutter 1.12. We developed the V2 API to make it easier for developers to incorporate The Flutter into existing native applications. By our count, over 80% of the Android add-ons to date have used the new Android API, so as of release 1.22, we are no longer maintaining the old V1 API.

If you are still using the Android V1 API, this may cause the following problems:

  • The newly developed plug-in cannot be used
  • Flutter tools- no - enable - android - embedding - v2The config flag has been removed by default
  • Older applications that are still using the V1 API will display a deprecation warning during build and point to the documentation that supports the new Android plug-in API

Also, if you still have the Flutter application based on the V1 Android API, it will work fine, but you will most likely encounter new plug-ins that only support the V2 API, which cannot be used by the V1 Android API. For more details, see the Major Changes documentation.

Brand new Button component

In previous releases, Flutter had a complete set of button components, but they were cumbersome to use, and the Material specification added several new button styles. So, in order to keep the Flutter in sync with the Material, we officially announce that Flutter 1.22 will introduce a new “Button”.

The naming convention for the new Button component also follows the Material Design principle, as shown below.

A good example is on DartPad. In addition, old components such as FlatButton, OutlineButton, RaisedButton, ButtonBar, ButtonBarTheme will not be deprecated, and developers can mix old and new buttons as needed.

New support for internationalization and localization

Since the release of Flutter, the application has been provided with better support for core functionality required for internationalization (I18N) and localization (L10N). In this new release, we have incorporated best practices for this functionality into our development tools, and, Hot reload support was enabled when new L10N information was added to update the application directly.

If you want to learn more about Flutter L10N, including localized messages with parameters, dates, numbers, and currencies, see the Flutter User guide.

In addition, if you are interested in i18N and L10N, you may also be more inertial with strings that are not contained in normal ASCII characters, such as Unicode and emoji. The Dart team also released the Characters software package to help developers work with Unicode (extended) character clusters. The library can help developers solve problems such as how to correctly abbreviating A String (such as “A 🇬🇧 text in English”) to the first 15 characters, using the String class, which can be abbreviated as “A 🇬🇧 text in”, It’s just 12 user-aware characters. On the other hand, characters can also be used to generate the correct abbreviation for “A 🇬🇧 text in Eng”.

This PR uses characters to handle these complex characters perfectly. For example, when a TextField has a maxLength limit, characters like 👨👩👦 now correctly count as single characters. In addition, this PR, in the project where the Flutter is, Character packs can be automatically used in a project without having to be added manually. Hopefully, this makes it easier to work with a variety of strings from all the locales. For more details on the Character package, see the article Doing Dart String Operations Correctly.

The Google Maps and WebView plug-ins are ready for production

The Flutter team usually takes a lot of consideration before labeling certain tags as “Production ready”, and we usually test them thoroughly before doing so. Both the Google_MAPS_flutter and Webview_flutter plug-ins are implemented using Platform Views, which allows the native UI components of Android and iOS to be embedded into the Flutter application. In this release of Flutter, we are pleased to announce that we have strengthened the framework layer to fully declare both plug-ins production-ready.

In Flutter 1.22, we added an alternative Platform Views implementation that fixes all known accessibility issues with keyboards and Android Views. In addition, it works with Android apis at level 19 and above (previously, level 20 was required). We’ve also made improvements to threading on iOS to make the platform view more efficient and reliable (and no longer require you to add the io.flutter. Embedded_views_preview flag to info.plist on iOS).

The Webview_Flutter plugin supports the new Android Platform Views mode, but currently needs to be manually enabled. We will enable it by default in future releases once it becomes more available to the wider community.

The Google Maps and WebView plug-ins have benefited from improvements to Platform Views. If you want to use the platform view to embed your native UI components on iOS or Android, See how to host native Android and iOS Views in your Flutter app with Platform Views.

The Navigator 2.0

If you have used Navigator before in the Flutter application, you may have noticed that the core data structure (the heap of routing pages the user is viewing) is not visible to you. You need to call navigator.pop () or navigator.push () each time you want to manage. For example, suppose you want to display a list of components on your home page and allow the user to click on a component to go to a detailed page for that color, as shown below.

We can implement these two simple UI pages in the following way:

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),  ); } Copy the code

Navigating between the two pages is very simple using Navigator 1.0:

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)),  ),  ),  ),  ); } Copy the code

You can create instances of both pages in the routing stack by simply calling navigater.push () to open the second page on the first page, but instead of explicitly creating a Containers list in the build method in ColorListScreen, The routing stack is not visible, so it is difficult to manage special cases such as deep linking of initial routes provided by native embedding, or urls from the Web or intents from Android, and also extremely difficult to manage embedding between different orders of the same page.

Navigator 2.0 solves these problems and more by making the page stack visible. The following code is another version between ColorListScreen and 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;  },  ),  ); } Copy the code

Here we explicitly create a Navigator and provide it with a list of pages representing the full stack, and we create an empty _selectedColor variable to indicate that no color has been selected yet, so ColorScreen is not displayed by default. When the user selects a color, we call setState() to update the status, the Flutter will re-call the build() method, and a ColorScreen page will be created on top of the ColorScreen.

You can update the returned state in the OnPopPage callback. For example, if the user falls back, they “deselect” the current color, so _selectedColor = null means that the page is no longer wanted to be displayed.

Navigator 2.0 looks like the rest of the Flutter, and that was her intention. It was declarative and imperative with Navigator 1.0. The idea was to unify the model between navigation and the rest of the Flutter, addressing many issues and adding functionality at the same time. In fact, this small example barely touches on Navigator 2.0. For more information, I recommend reading Declarative Navigation and routing in Flutter

In addition, Navigator 1.0 is still available and won’t be dead any time soon, so if you already like the routing mode, you can still use it. However, if you try Navigator 2.0, we think you’ll like it.

Preview function

Restore the status of Android

Another new feature to try out in this new release is support for Android state restoration. This is one of our most popular features on Github, with 217 likes!

Consider that readers may not be familiar with this requirement of state restoration. Mobile operating systems may kill applications in the background to reclaim resources from foreground applications. When this happens, the operating system informs the app that it has been terminated, so the developer can quickly save the current UI state so that it can be restored when the user returns to the app again. If this feature is complete, it can provide a seamless experience for users and make better use of the device’s resources. Currently, The Flutter does not support state restoration, and it is difficult to do this on its own without support from the framework layer, so we announced a basic implementation of this functionality in Flutter 1.22.

Here is a simple example to restore the default Application state of Flutter Counter:

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),  ); } Copy the code

Briefly, each component has a storage bucket that RestorationMixin registers with with a unique ID. By using a RestorableProperty type (like RestorableInt here) to store UI-specific data and registering that data with the state recovery feature, the data is automatically saved before Android terminates the application and restored when it is up and running again. That’s right, Restoration * can store any type of data, such as RestorableInt, RestorableString and RestorableTextEditingController (etc.) will be restored.

If the data type you want to restore is not covered built-in, RestorableProperty

can also be used to create your own.

To automate testing of state recovery, we also added a new restartAndRestore API to WidgetTester. If you want to test it manually, the easiest way to do this is to open the Flutter app on an Android device that has enabled state recovery, enable “Do not retain activity” in the Android Developer Settings (pictured below), then run the Flutter app, put it in the background, and then return. At this point, Android will terminate your application before resuming it, and you can check to see if everything is working as expected.

While we’ve already released a preview of state Recovery, there’s a lot more work to do. For example, state recovery needs to be available not only on Android, but also on iOS applications. In addition, we are working on optimizing our built-in components so that they remain in their state by default during the recovery process. We already have support for this functionality in the ListView and SingleChildScrollView classes (which remember where the user scrolled) and TextFields classes (which restore the text they entered), and we are planning to extend it to other components.

However, due to Navigation (1.0 or 2.0), this feature is only currently available in preview, that is, your users won’t be able to experience it yet, we will release it in the Beta and in the next stable release of Flutter.

Rolling performance optimization

The Flutter team also worked with the Google kernel to greatly improve page scrolling due to the fact that the input and display frequencies were out of sync. For example, the Pixel 4 input runs at 120Hz, while the display runs at 90Hz, a mismatch that can cause performance degradation when scrolling. Using the new resamplingEnabled flag, you can solve this problem as follows:

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

Depending on the frequency difference involved, enabling this flag can reduce the flutter while scrolling to 97%, and we have plans to enable this feature by default in future releases when we decide that this is the best experience.

read

This article does not cover updates to the Flutter developer tool due to space constraints, but you can read it:

The original official: https://medium.com/flutter/announcing-flutter-1-22-44f146009e5f

My blog: https://meandni.com/2020/09/28/d206/

Follow the official account “Meandni” to read mobile development technology and the latest technology developments in time.