Flutter 3.3 / Dart 2.18変化点の要約

『 Flutter 3.3 と Dart 2.18 の変化点を知りたい!』

そんなあなたに向けて、Flutter 3.3 / Dart 2.18の変化点をまとめて紹介いたします。

これを見ればFlutter 3.3のアップデートで何が変わったのか一気に知ることができます!
ぜひ読んでみてください!

Flutter 3.3の変化点

Flutter 3.3 では5,687ものプルリクエストがマージされたとのことです。

Web , デスクトップ, テキストハンドリングのパフォーマンスでの向上と、
go_router パッケージ、Dev tool 、VS codeの拡張機能のアップデートを含みます。

SelectionArea ウィジェット

Flutter 3.3 にて、SelectionArea ウィジェットが追加されました。

今まで、FlutterのWebアプリでのテキスト選択は思うような挙動をしていませんでした。
一回のマウスカーソルのスワイプで複数行選択できるようにするのは、簡単ではありませんでした。

SelectionAreaウィジェットにより、
このウィジェットの子は、全て自由にテキスト選択が可能となります。

例えば、Scaffoldのようなウィジェットツリーの根元の部分を
SelectionArea ウィジェットで囲うだけで、複数行の選択が可能となります。

詳しくはこちら

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SelectionArea Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'SelectionArea Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  Widget build(BuildContext context) {
    return SelectionArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: Center(
          child: DefaultTextStyle.merge(
            style: const TextStyle(
              fontSize: 20,
              color: Colors.black,
            ),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: const <Widget>[
                Text('選択可能なテキスト1'),
                Text('選択可能なテキスト2'),
                Text('選択可能なテキスト3'),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

トラックパッドの入力対応

Flutter 3.3 ではトラックパッドの入力に対応しました。
リッチでスムーズなコントロールを可能にするだけでなく、
いくつかの誤操作を生むような事象の削減をしています。

詳細はこちらをご覧ください。
また、以下のプルリクエストを参照ください

スクリブル

Flutter 3.3 より、iPad OSとApple Pencil で可能な、スクリブルでの手書き入力に対応しました。

CupertinoTextFieldTextFieldEditableTextのウィジェットで、
Flutter 3.3にアップデートするだけで可能となります。

テキストインプット

Flutter 3.3では、プラットフォームのTextInputPluginから
詳細なテキスト入力の更新を受け取ることができるようになりました。
以前はTextInputClientは古いものと新しいものの差分は保持せず、
新しく編集された状態のみ配信していました。
TextEditingDeltasDeltaTextInputClientにアクセスすることにより、
入力によって伸縮する、装飾付きの範囲を持つ入力フィールドを作成可能です。

詳細は、こちらをご覧ください。

Material Design 3

FlutterへのMaterial Design 3 のコンポーネントのマイグレートが行われています。
今回のリリースでは、IconButton, Chips, AppBarのアップデートがなされています。

詳細については元記事にてGIFで紹介されています。

Material 3に関する動向はこちらで確認することが可能です。

Windows

Flutter3.3から、Windows のデスクトップアプリケーションのバージョンを、プロジェクトのpubspec.yamlファイルとビルド引数から設定可能になりました。
(以前はWindows アプリケーション固有ファイルからの設定でした。)
これにより、アプリケーションが更新された際にエンドユーザーが
最新版を取得するための自動アップデートを
より簡単に行うことができるようになります。

より詳細な情報は、ドキュメントマイグレーションガイドをご覧ください。

go_router パッケージ

画面遷移ロジック設計のシンプル化をするための
Flutter チームによってメンテナンスされているパッケージ、
go_routerについてです。
最新版(5.0)では、redirectの引数にBuildContextが追加されたり、
navigatorBuilderの削除等の破壊的変更が行われています。(詳細

詳細はこちらをご覧ください。

2022年8月31日10時時点でまだgo_router 5.0 は更新されていませんでした。

VS Code 拡張機能の強化

Visual Studio Code のFlutter 拡張機能がアップデートされました。
その一つがdependencyの追加機能です。
Dart: Add Dependency を利用することで、
複数のパッケージを一気に追加することが可能です。

アップデートの詳細は以下を参照ください。

DevTool のアップデート

DevTool に対して、UXとパフォーマンスの向上を含む、
多くのアップデートがされました。
その一つが、データ表示の向上で、より早く表示され、多くのイベントのリストのスクロールがスムーズになりました。(#4175).

その他の向上については以下をご覧ください。

パフォーマンス:ラスターキャッシュの向上

Flutter 3.3にて、アセットからの画像読み込みのパフォーマンスが、
コピーの削除と、ガベージコレクション(GC)の圧迫の削減により向上しました。
ベンチマークにて画像読み込み時間が約2倍向上したとのことです。

元記事では向上に関してより詳細なロジックや、
向上具合の画像が記載されています。

詳細はこちらのドキュメントをご覧ください。

安定性:iOS ポインタ圧縮の無効化

Flutter 2.10 stable リリースにて、
iOS上でDartのポインタ圧縮の最適化を可能にしました。
しかしポインタ圧縮はDartのヒープ領域用の仮想メモリを大きく圧迫し動きます。
ポインタ圧縮を無効にした場合、
Dart オブジェクトによって消費されるメモリが増加しますが、
Flutterアプリケーションの非Dart部分に使用できるメモリも増加するため、
こちらの方が全体として望ましいことから無効化しています。

将来的にこの最適化の有効化を行うことはあり得るとのことです。
(詳細は元記事をご確認ください。)

API の向上 : PlatformDispatcher.onError

以前はアプリケーションのエラーや例外全てをキャッチするために
カスタム Zoneを設定する必要がありましたが、
今回のリリースで、カスタム Zoneを使う代わりに、
PlatformDispatcher.instance.onError コールバックを使うことが推奨されます。

詳細はこちらのドキュメントをご確認ください。

API の向上 : フラグメントプログラムの変更

GLSLで書かれ、pubspec.yamlshaders:セクションでリスト化された
フラグメントシェーダーはエンジンによって
理解されるフォーマットにて自動的にコンパイルされ、
アセットとしてアプリケーションにバンドルされるようになりました。
このおかげで、第三者のツールを使って
シェーダーを手動でコンパイルする必要がなくなります。

この変更の例は、こちらをご覧ください。

API の向上 : フラクショナル トランスレーション

以前はFlutter エンジンは合成レイヤーを
正確なピクセル境界に常に揃えていました。
デスクトップのサポートが追加されてから、
観測可能なスナッピング動作(ぶれ)に気がつきました。
画面のデバイスピクセル比が一般的にデスクトップでは低いためです。
例えば、低いデバイスピクセル比の画面では、
ツールチップがフェードインする際にスナッピングが見えます。
このスナッピングは新たなiPhoneモデルでは不要と決定し、
ピクセルスナッピングの削除をしました。

サポートプラットフォームの変更:32-bit iOS の非推奨化

32-bit iOS デバイスとiOS バージョン9、10
(iPhone 4S、iPhone 5、iPhone 5C、第2、3、4世代 iPad)
のサポートが終了します。
これらのデバイスでは、Flutter3.3以降で作成されたアプリは実行されません。

サポートプラットフォームの変更:macOS 10.11、10.12の非推奨化予告

2022年 第4クォーターのstableリリースで、
macOS のバージョン10.11、10.12に対するサポートを終了します。

サポートプラットフォームの変更:ビットコードの非推奨化予告

来たるXcode 14 のリリースにて、
ビットコードでのiOSアプリのアップロードができなくなります。(詳細はこちら)
これにより、Flutterも将来のstableリリースでビットコードに対するサポートを終了します。

通常、Flutterアプリはビットコードは可能になっていません。
ビットコードの可能化の変更については元記事に詳細が記載されています。
その他ビットコードでの配布の詳細はこちらをご確認ください。

Dart 2.18の変化点

DartとObjective-C/Swift との相互運用の導入

Dart 2.18でmacOS、iOSのプラットフォームのAPIで通常使用されるように、
Objective-C/Swiftのコードを呼び出すことができます。
DartはCLIアプリからバックエンドのコード、Flutter UIまで、
この相互運用のメカニズムをサポートします。

Dart API ラッパー生成ツール、ffigenで、
APIヘッダーからこれらのバインディングを構成することができます。

例で紹介します。

Objective-C を使ったタイムゾーンの例

元記事で紹介されている例の要点をまとめたものとなります。

macOS はNSTimeZone クラスで公開されている
タイムゾーン情報を要求するためのAPIを持ちます。
ユーザーのデバイスにて設定されたタイムゾーンと
UTCタイムゾーンのオフセットを取得するためにAPIを実行できます。

以下はGMTのタイムゾーンとのオフセットを取得するための
タイムゾーンAPIの実行例です。

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSTimeZone *timezone = [NSTimeZone systemTimeZone]; // Get current time zone.
        NSLog(@"Timezone name: %@", timezone.name);
        NSLog(@"Timezone offset GMT: %ld hours", timezone.secondsFromGMT/60/60);
    }
    return 0;
}

API ヘッダーを含むFondation.hをインポートしています。
また、NSTimeZoneクラスから、systemTimeZoneメソッドを呼び出しています。
このメソッドは、デバイスの設定のタイムゾーンの
NSTimeZoneインスタンスを返します。

このアプリで、以下の実行結果が得られます。

Timezone name: Europe/Copenhagen
Timezone offset GMT: 2 hours

新しいObjective-C相互運用機能を使用して、
Dartでこの結果を再現してみましょう。

Dart CLI でアプリを作ります。

dart create timezones

pubspec.yaml ファイルにて、ffigenの設定をします。
この設定はヘッダーファイルを指し示し、
どのObjective-C インターフェースがラッパーを生成する
必要があるかを示します。

ffigen:
  name: TimeZoneLibrary
  language: objc
  output: "foundation_bindings.dart"
  exclude-all-by-default: true
  objc-interfaces:
    include:
      - "NSTimeZone"
  headers:
    entry-points:
      - "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/
         Headers/NSTimeZone.h"

これで、NSTimezone.hのヘッダーに対してObjective-Cバインディング
することを選択し、
NSTimeZoneインターフェースにAPIのみが含まれます。

ラッパーの生成は以下のコマンドでffigenを実行することで可能です。

dart run ffigen

このコマンドで、生成された一連のAPIバインディングを含む、
foundation_bindings.dartが作成されます。
このバインディングファイルを使うことで、
Dartのmainメソッドを書くことができます。

前述のObjective-Cのコードと対応させると、以下のようになります。

void main(List<String> args) async {
  const dylibPath =
      '/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation';
  final lib = TimeZoneLibrary(DynamicLibrary.open(dylibPath));

  final timeZone = NSTimeZone.getLocalTimeZone(lib);
  if (timeZone != null) {
    print('Timezone name: ${timeZone.name}');
    print('Offset from GMT: ${timeZone.secondsFromGMT / 60 / 60} hours');
  }
}

このような新たなサポートがDart2.18から可能となります。
これによりDart のmacOS/iOSのAPI呼び出しサポートの相互運用は加速します。
また、これによりFlutterのプラグインは補完されます。
どんなDartアプリでも実行可能な新たなサポートが追加され、
macOS/iOSのAPIをDart コードから直接呼び出せるようになります。

より詳細な情報は、こちらをご確認ください。

マルチプラットフォームアプリでのプラットフォーム固有のネットワーキング

Dartはマルチプラットフォームのhttpライブラリを含んでいます。
このライブラリはプラットフォーム固有の内容を考えること無しで
コードを書くことができるようにしています。
ですが時々、特定のホストプラットフォームの
ネットワーキングAPIにコードを記述したい場合があります。

例えば、Appleのネットワーキングライブラリ、NSURLSessionはWiFiのみのネットワークを指定したり、VPNが必要であることを指定したりできます。
これらのユースケースをサポートするために、macOS/iOSプラットフォームに対して、新たなネットワーキングパッケージ、cupertino_httpを作成しました。
これは前章で紹介したObjective-Cの相互運用で作成されています。
FoundationのAppleのネットワークAPIから生成された、APIラッパーの大規模な集合を使用しています。

cupertino_httpの例は、元記事をご確認ください。

アプリを可能な限りマルチプラットフォームに保つために、
基本的なhttp操作のためのマルチプラットフォームなhttp APIの集合を維持し、
使用するネットワークライブラリをプラットフォームごとに構成できるようにしました。

Dart 2.18では試験的に2つのプラットフォーム固有のhttpライブラリの
サポートを提供します。

  • cupertino_http : macOS/iOSに対する、NSURLSessionを基盤とする
  • cronet_http :  Android上で人気のネットワークライブラリのCronetを基盤とする

共通のクライアントAPIをいくつかのHTTP 実装と組み合わせることで、
両者の長所を活用できます。
全てのプラットフォームの単一のソースセットでアプリをメンテしながら、
プラットフォーム固有の動作を得ることができます。

型推論の向上

Dartではジェネリクスを使った関数を多く使います。
例えばfoldメソッドを考えましょう。
以下の例はint型の要素のリストの合計を計算する例です。

List<int> numbers = [1, 2, 3];
final sum = numbers.fold(0, (x, y) => x + y);
print(‘The sum of $numbers is $sum’);

Dart2.17では以下の型に関するエラーが出ます。

line 2 • The operator ‘+’ can’t be unconditionally invoked because the receiver can be ‘null’.

これは、xの型が不確かなために発生します。
修正は以下のコードのように型を指定することで可能です。

final sum = numbers.fold(0, (int x, int y) => x + y);

Dart 2.18では型推論が強化され、xynullでないint型と推測され
上記の例でも静的解析でエラーとならなくなります。

これにより、より簡潔なDartコードを記述できるようになります。

非同期処理のパフォーマンスの向上

Dart VM が asyncメソッドと、async*/sync*ジェネレーター関数を
適用する方法が改善されています。
これにより、コードサイズが削減されます。

例:GoogleアプリのAOTスナップショットのサイズが10%削減

また、マイクロベンチマーク全体でパフォーマンスが向上しました。

これらの変更は追加で小さな挙動の変更を含みます。
詳細はこちらをご確認ください。

pub.dev の向上

pub.dev パッケージリポジトリに2つの変更を加えました。

  • スポンサーシップを容易にするために、
    pubspecでfundingのタグをサポートするようになりました。
    fundingに設定したリンクはpub.devのサイドバーに表示されます。(詳細)
  • オープンソースパッケージを奨励するために、
    pub.devの自動パッケージスコアリングで、
    OSI承認済ライセンスを使用するパッケージに10ポイントを追加します。

重大な変更

Dart 2.18での重大な変更(breaking changes)を紹介します。

  • dart2jsdartanalyzarコマンドの廃止
  • .packagesファイルの使用の中止
  • Object型を継承しないクラスのmixinの使用不可。(breaking change #48167).
  • dart:iouriのプロパティ、RedirectExceptionnull許容に(breaking change #49045).
  • 非推奨になっていたdart:ioのネットワーキングAPIのスネークケースの定数の削除(breaking change #34218)
  • Dart VMは、終了時に初期設定を復元しないよう変更(breaking change #45630)

null safety

2023年半ばでのリリースで、
非null safety 、または完全にnull safetyでないものに対する
サポートを終了する、と告知されました。

これは、Dart 2.11以前のサポートの終了を意味します。
SDK の設定の下限が2.12未満のpubspec ファイルは、
Dart 3以降では解決されなくなります。

null safetyへの移行具合については元記事を参照ください。

まとめ

本記事では、Flutter 3.3 / Dart 2.18の変化点をまとめて紹介しました。

いかがだったでしょうか?

プラットフォーム追加のような大きい変化点は無いながらも、
SelectArea ウィジェットのような魅力的なウィジェットの追加は、
とても嬉しいですね。

Flutter 3.3、Dart 2.18 、早速使ってみようと思います。

本記事があなたのアプリ開発の一助となれば幸いです。

Flutterを一緒に学んでみませんか?
Flutter エンジニアに特化した学習コミュニティ、Flutter大学への入会は、
以下の画像リンクから。



編集後記(2022/8/31)

Flutter 3.3 / Dart 2.18 の記事でした。

個人的には、VS Code 機能拡張の Dart: add dependencyにとても感動しました。

パッケージインストールがとても楽になります。

あなたは、今回のアップデート、どう思いましたか?

ぜひ感想をTwitter等で共有いただければと思います。

ますます盛り上がっていくFlutter、楽しんでいきましょう!

週刊Flutter大学では、Flutterに関する技術記事、Flutter大学についての紹介記事を投稿していきます。
記事の更新情報はFlutter大学Twitterにて告知します。
ぜひぜひフォローをお願いいたします。

タイトルとURLをコピーしました