今回は、Flutter 2.0より実装された「Null Safety」について詳しく解説していきます。
聞いたことはあるけどあまり詳しくは知らないと言った方に必見の内容です。
ぜひ最後までご覧ください。
Null Safety対応バージョン
2021年3月、Flutterの開発言語であるDartがNull Safetyに対応されました。
このときリリースされたバージョン「2.12」以降のDartにてNull Safetyを利用することができます。
同時期にリリースされたFlutter 2.0を使用すると自動的にDart 2.12を使用することができます。
(2022年5月現在の最新バージョンはFlutter 3.0.1/Dart 2.17.1)
Null Safetyとは
Null Safetyとは、プログラムの実行時にnullが原因で発生し得るエラーを発生させない仕組みのことです。Null安全などと呼ばれることもあります。
このNull Safetyは変数の定義の際に大きく関係してきます。
基本的には、変数の定義の際に値を入れない場合はnullとなります。
Null Safetyは、こういった変数の定義の際に、その変数がnullを許容するかしないかを明示的に書くルールと認識してもらえれば大丈夫です。
詳しくは公式ドキュメントもご覧ください。
null非許容のデータ型を扱う
変数をnull非許容のデータ型で定義することで、その変数にはnullが入っていないことを保証することができます。
これにより、Textウィジェットなどのデータを必ず必要とする場面で変数を使うときのプログラムの安全性が高まります。
具体的な定義方法は以下です。
String name;
上記のような定義の場合は、nullを許容していないString型なのに初期値が代入されていないのでエラーが発生してしまいます。
そのため、初期値を入れる必要があります。
String name = '奥野';
また、クラスのメンバ変数をnull非許容で定義する場合もデフォルトで値を入れる、もしくは必ず引数を渡す必要があります。
//初期値を入れる場合
class User1 {
String name;
User1({this.name = '奥野'});
}
//引数を必須にする場合
class User1 {
String name;
User(this.name);
}
class User2 {
String name;
User({required this.name});
}
null許容のデータ型を扱う
nullが入ることを許容するデータ型はデータ型の後に「 ? 」をつけます。
具体的な定義方法は以下です。
String? name;
このようにString? とすることでnameという変数はnullを入れることができます。
なので上記のように初期値を入れずに定義を行っていてもエラーが発生しません。
ただし、nullを許容する場合にはいくつか記述の上で気をつけなければならないことがあります。
null許容の変数を扱う上での注意点
①変数の値がnullでないことが確信的な場合は!を使用する
変数の値が文脈から判断して確実にnullではないという場合は、基本的に条件分岐などでnullの対応をせずに「 ! 」をつけることで確実にnullではありませんと明示する方が得策です。
以下のように、Userクラスのメンバ変数であるnameをTextウィジェットで表示してみます。
class User {
String? name;
User(this.title):
}
User userInstance = User('奥野');
Text(userInstance.name!); //!をつけることでnullではないことを確約する
例えば、アプリでマイページにアクセスした際にユーザーの名前を表示するというシチュエーションを想定します。
マイページにアクセスするには必ずログインしていないといけない設計になっているとします。
この場合、マイページにアクセスができているということはユーザーの名前は確実に取得できていなければいけないはずです。
なのでこういったケースの場合でのnull対応は、!をつけることでnullではありませんと明示しておくのがいいでしょう。
こうすることで、もしもユーザーの名前がnullの状態でマイページにアクセスしてしまっているケースがあった場合はエラーが発生するので、開発者にバグを気づかせてくれます。
②変数の値がnullだった場合に適用する値を??で明示する
変数の値がnullの場合に適用する値を「 ?? 」を使って明示しないといけない場合があります。
①と同じUserクラスを用いてnullの可能性がある場合のTextウィジェットでの表示方法をみてみましょう。
User userInstance = User('奥野');
Text(userInstance.name ?? '名前はありません'); //??の左側に書いている変数がnullの場合、右側に書いている内容を適用する
このように文脈的にもnullの可能性がある場合は「 ?? 」を用いてnullの場合の値を明示する必要があります。
③メソッドや変数へのアクセスの結果がnullになってもいい場合は?を書く
nullを許容している値のメソッドなどにアクセスする場合、その結果がnullになってもいい場合は「 ? 」を書く必要があります。
List<String> nameList = [];
print(nameList.length); //結果: 0
List<String>? nameList2;
print(nameList.length); //結果: エラー
print(nameList?.length); //結果: null
メソッドやメンバ変数にアクセスする際に「 ?. 」とすることで、その値へのアクセスを中止しnullを取得することができます。
Null Safetyを有効にする方法
自分のFlutterプロジェクトにNull Safetyを有効にするには、プロジェクトディレクトリ内にあるpubspec.yamlファイルにて以下のように指定する必要があります。
environment:
sdk: ">=2.12.0 <3.0.0" // 最低でも2.12.0以上にする必要がある
こちらはプロジェクトで使用できるDartのバージョンの範囲を指定しています。
上記の場合だと2.12.0 ~ 3.0.0までのDartバージョンであれば使用可能ということを意味します。
こちらの下限の設定は現在使用しているFlutterのバージョンに対応したDartバージョンを指定することをお勧めします。
(2022年5月現在の最新バージョンFlutter 3.0.1の場合なら >=2.17.1にする)
逆にNull Safetyを無効化する方法は以下の記事にて紹介しています。興味がある方は併せてご覧ください。
Null Safetyが対応済みのパッケージを調べる方法
使用しているパッケージがNull Safetyに対応しているかどうかを確認するには、ターミナルで以下コマンドを実行します。
$ flutter pub outdated --mode=null-safety
私が開発に携わっているアプリの状況を確認したものが以下です。
Resolvableの項目に「 ✔️ 」マークがついているものはNull Safetyに対応しています。
こちらに記載されているバージョン以上にするとNull Safetyに対応することができます。
私の場合は全てのパッケージがNull Safetyに対応しています。
おわりに
今回は、Flutter 2.0より実装された「Null Safety」について詳しく解説してみました。
最近Flutterを始めた方は元からNull Safetyが実装されている環境で開発されているので導入のハードルは高くないかと思いますが、昔から開発をされている方は早めにNull Safetyの導入をすることをおすすめします。
これにより実行速度の改善や、アプリがクラッシュするリスクなどを減らすことができるのでぜひ積極的に活用していきましょう。
コメント