Open10

趣味のFlutterアプリのnull safety対応

YuheiNakasakaYuheiNakasaka

現状の環境。仕事の都合もあってちょっと古いのを趣味環境でも合わせて使ってる。

% flutter --version
Flutter 1.22.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 7891006299 (3 months ago) • 2020-12-10 11:54:40 -0800
Engine • revision ae90085a84
Tools • Dart 2.10.4
YuheiNakasakaYuheiNakasaka

公式のマイグレートガイドをみながらやっていく。
https://dart.dev/null-safety/migration-guide

まずはそもそもDartが2.10.4なのでこれを2.12以上にしていく。

せっかくなのでFlutter 2.0.0にアップグレード。これで一気にDartのSDKも2.12になる。

flutter upgrade

pubspec.yamlに手を加えていく。

environment:
  sdk: ">=2.12.0 <3.0.0"
YuheiNakasakaYuheiNakasaka

次に依存関係の対応状況をチェック。video_playerは自前のfork版を使ってる影響なのか非対応扱いになってる...。

$ dart pub outdated --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
[✓] indicates versions opting in to null safety.

Package Name            Current                     Upgradable                  Resolvable                  Latest

direct dependencies:
app_settings            ✗4.0.4                      ✓4.1.0                      ✓4.1.0                      ✓4.1.0
cloud_firestore         ✗0.14.4                     ✗0.14.4                     ✓1.0.1                      ✓1.0.1
cupertino_icons         ✗1.0.0                      ✓1.0.2                      ✓1.0.2                      ✓1.0.2
device_info             ✗1.0.0                      ✓2.0.0                      ✓2.0.0                      ✓2.0.0
enum_to_string          ✗1.0.14                     ✗1.0.14                     ✗1.0.14                     ✓2.0.0-nullsafety.1
equatable               ✗1.2.6                      ✓2.0.0                      ✓2.0.0                      ✓2.0.0
firebase_analytics      ✗6.3.0                      ✗6.3.0                      ✓7.1.1                      ✓7.1.1
firebase_auth           ✗0.18.4+1                   ✗0.18.4+1                   ✓1.0.1                      ✓1.0.1
firebase_core           ✗0.5.3                      ✗0.5.3                      ✓1.0.1                      ✓1.0.1
firebase_messaging      ✗7.0.3                      ✗7.0.3                      ✓9.0.0                      ✓9.0.0
firebase_remote_config  ✗0.4.3                      ✗0.4.3                      ✓0.9.0-dev.0                ✓0.9.0-dev.0
flutter_inappwebview    ✗4.0.0+4                    ✗4.0.0+4                    ✓5.1.0+4                    ✓5.1.0+4
flutter_riverpod        ✗0.12.4                     ✓0.13.1                     ✓0.13.1                     ✓0.13.1
fluttertoast            ✗7.1.6                      ✗7.1.8                      ✓8.0.1-nullsafety.0         ✓8.0.1-nullsafety.0
package_info            ✗0.4.3+4                    ✓2.0.0                      ✓2.0.0                      ✓2.0.0
pub_semver              ✗1.4.4                      ✓2.0.0                      ✓2.0.0                      ✓2.0.0
rxdart                  ✗0.25.0                     ✓0.26.0                     ✓0.26.0                     ✓0.26.0
url_launcher            ✗5.7.10                     ✓6.0.2                      ✓6.0.2                      ✓6.0.2
video_player            ✗2.0.0-nullsafety.6 (path)  ✗2.0.0-nullsafety.6 (path)  ✗2.0.0-nullsafety.6 (path)  ✗2.0.0-nullsafety.6 (path)

dev_dependencies:
flutter_launcher_icons  ✗0.8.1                      ✗0.8.1                      ✓0.9.0                      ✓0.9.0
pedantic                ✗1.9.2                      ✓1.11.0                     ✓1.11.0                     ✓1.11.0
pedantic_mono           ✗1.10.0+3                   ✓1.11.0+2                   ✓1.11.0+2                   ✓1.11.0+2

12 upgradable dependencies are locked (in pubspec.lock) to older versions.
To update these dependencies, use `dart pub upgrade`.

9  dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
YuheiNakasakaYuheiNakasaka

ひとまず対応してるライブラリに関してはLatestのversionに上げてみる。

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2

  firebase_core: ^1.0.1
  firebase_auth: ^1.0.1
  cloud_firestore: ^1.0.1
  firebase_analytics: ^7.1.1
  firebase_remote_config: ^0.9.0-dev.0
  firebase_messaging: ^9.0.0

  flutter_riverpod: ^0.13.1
  rxdart: ^0.26.0
  equatable: ^2.0.0

  enum_to_string: ^2.0.0-nullsafety.1
  package_info: ^2.0.0
  device_info: ^2.0.0
  app_settings: ^4.1.0
  pub_semver: ^2.0.0
  url_launcher: ^6.0.2
  fluttertoast: ^8.0.1-nullsafety.0
  flutter_inappwebview: ^5.1.0+4
  video_player:
    path: ../flutter-plugins/packages/video_player/video_player

dev_dependencies:
  flutter_test:
    sdk: flutter
  pedantic: ^1.11.0
  pedantic_mono: ^1.11.0+2
  flutter_launcher_icons: ^0.9.0

自前のvideo_player以外は全て対応versionを指定してみてから下記のコマンドを叩く。Got dependencies!が出た。

$ dart pub get
...
Got dependencies!
YuheiNakasakaYuheiNakasaka

結構どでかいバージョンアップデートを行ったのでインターフェースの変わってるライブラリとかも出てきた。特にFirebaseMessagingはかなり変わってたので地道に直していく。

YuheiNakasakaYuheiNakasaka

ちなみにdart migrateを実行すると下記のエラーが出る。何故...。仕方ないので手作業でnull-safetyのコードに書き換えることにした。大体修正箇所は100件程度。大きなロジックの変更とかはないのでlate,required,!,?あたりを付け加えたり無駄なnullチェックを消したりしていくのが大多数。

$ dart migrate
The migration tool didn't start, due to analysis errors.

The following steps might fix your problem:
1. Set the lower SDK constraint (in pubspec.yaml) to a version before 2.12.
2. Run `dart pub get`.
3. Try running `dart migrate` again.

このドキュメントを読むとどう書き換えると良いのか理解進むかも。
https://dart.dev/null-safety/understanding-null-safety

YuheiNakasakaYuheiNakasaka

一通りerrorとwarningを消してdart migrateを実行したら下記のような結果になった。

$ dart migrate
Migrating /Users/razokulover/src/github.com/YuheiNakasaka/ag_viewer

See https://dart.dev/go/null-safety-migration for a migration guide.

Analyzing project...
[---------------------------------------------------------------------------------------------------------------------------------------------------/]All sources appear to be already migrated.  Nothing to do.
YuheiNakasakaYuheiNakasaka

実行してみる。

$ flutter clean
$ flutter run --no-sound-null-safety

後回しにしてた自前のvideo_playerがnull-safety対応出来てないぞとエラーが出た。そりゃそうか。いったんビルドを通すために本家の最新版を使う。これと引き換えにaudioのbackground再生の機能が失われる。あとでどうするか考えることにした。

あとよくみたらfirebase_analyticsfirebase_remote_configはまだnull-safety対応してない。dart pub outdated --mode=null-safetyでResolvableにチェックマークがついてたからイケるのかと思ったがこれも対応待ちである。

YuheiNakasakaYuheiNakasaka

video_playerに関してはこのPRこのPRが合わさったやつが欲しくて雑にこんな感じのforkを作った。webのプラグインは不要だったのでpubspec.yamlから外したりもした。
https://github.com/YuheiNakasaka/flutter-plugins/tree/fix/ios-hls-bug/packages/video_player/video_player

そんでアプリの方のpubspec.yamlの指定を下記のように変更。これでfork版のvideo_playerを使えるようになる。

video_player:
    git:
      url: git@github.com:YuheiNakasaka/flutter-plugins.git
      path: packages/video_player/video_player
      ref: fix/ios-hls-bug