Flutter: DBのupgradeで列追加すると「'Null' is not a subtype」のエラー
結論:Dart Data ClassプラグインのfromMapメソッド部分を、null許容「?」のキャストに修正する
2022/6/23 Flutter エラー・バグ日記
sqfliteのデータベースをupgradeして、データ列を追加し、既存データをアプリ内に読み込んだら、
E/flutter (#####): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type 'Null' is not a subtype of type 'double' in type cast
E/flutter (#####): #0 new testValueO.fromMap (package:・・・/・・・/・・・.dart:271:43)
・・・
のエラーが発生。
既存データでは、追加した列(ここでは列の名称を「testValueO」とする)にデータが入っていない状態(null)となるので、追加した列は、「REAL NULLABLE」(null許容)で設定していた。
また、モデルクラス(sqfliteデータベースに格納するデータセットを、必要な変換メソッドとセットで定義するクラス)の方でも、追加列の値を入れる変数は「final double? testValueOn;」のように、null許容で定義しておいた。
そのため、エラーにはならないはず、、、と不思議に思ったが、エラー文をよく見ると、2つ目のエラー文で「.fromMap」メソッド(Map型からモデルクラスの型に変換するメソッド)に問題が生じていると分かった。
「.fromMap」メソッドは、「Dart Data Class」プラグインを使用して、モデルクラスを作成する際に、自動生成させていた。
モデルクラスの作成には、「freezed」パッケージを使用するのが一般的かと思うが、「freezed」は、コマンドラインからのコード生成が必要になり、エラーで止まることもあるので、個人的には苦手だった。。
これに対し、「Dart Data Class」は、クラス名と変数名だけを書いたら、クラスの中で、右クリック→「Generate」→「Data Class Section」→「OK」とするだけで、エラーが発生することなく、必要な変換メソッドを揃えたモデルクラスを生成できるので、愛用していた。
そこで、生成した「.fromMap」メソッド部分を確認したところ、下記のように、null許容(?マークあり)で定義したはずの変数を含め、全ての変数が、null不可(?マークなし)でキャスト(型変換)されていることが分かった。
factory TestDataO.fromMap(Map<String, dynamic> map) { return TestDataO( xxxxxO: map['xxxxx'] as String, ・・・・・ // 変数testValueOは、double? 型で定義していたのに、 // ここでは?が付かずに、null不可でキャストされてしまっている testValueO: map['testValueO'] as double, ); }
「Dart Data Class」は、2021年8月にnull Safety対応を完了したと思っていたが、「.fromMap」メソッドのキャスト部分は、対応がまだ不十分なのかもしれない。これには気づかなかった。。
仕方なく、null許容にしたい変数については、手動で「as double?」のように、?を加える修正をしたら、無事エラーは発生しなくなった。
こうした注意点はあるものの、「Dart Data Class」は非常に便利なプラグインであることに変わりはないので、引き続き利用したいと思う。
リリースしたアプリ(全てFlutterで開発)
個人アプリ開発で役立ったもの
おすすめの学習教材
\超初心者向けでオススメな元Udemyの講座/
\キャンペーン時を狙えば安価で網羅的な内容が学べる(日本語訳あり)/
\Gitの基礎について無料で学べる/
おすすめの学習書籍
\実用的。image_pickerに関してかなり助けられた/
\Dartの基礎文法を素早くインプットできる/