前提・実現したいこと
SharedPreferencesを利用してローカル保存するように実装しています。
ですが、起動しません。
発生している問題・エラーメッセージ
[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The getter 'length' was called on null. Receiver: null と言うエラーが表示されます
該当のソースコード
Flutter
1 2import 'dart:convert'; 3 4import 'package:flutter/cupertino.dart'; 5import 'package:flutter/foundation.dart'; 6import 'package:freezed_annotation/freezed_annotation.dart'; 7import 'package:state_notifier/state_notifier.dart'; 8import 'package:todo_sql/todo.dart'; 9import 'package:uuid/uuid.dart'; 10import 'package:shared_preferences/shared_preferences.dart'; 11part 'todos_state.freezed.dart'; 12 13 14@freezed 15abstract class TodosState with _$TodosState { 16 const factory TodosState( {//TodosStateのクラスをチェック 17 @Default(<Todo>[]) List<Todo> todos,//すべてのTodoが入るtodos 18 }) = TodosStateData;//TodosStateDataであればデータの読み込みが終わったという判断ができるように 19 const factory TodosState.loading() = TodosStateLoading;//TodosStateLoadingであればまだ読み込み中 20} 21 22class TodosController extends StateNotifier<TodosState> with LocatorMixin { 23//LocatorMixinをmixinする事でcontextにあるproviderへのアクセスを容易する 24 TodosController() : super(const TodosState.loading()); 25 26 final _uuid = Uuid(); 27 28 @override 29 void initState() async { 30 super.initState(); 31 await Future<void>.delayed(const Duration(seconds: 3));//initStateで3秒間ウエイトを入れ,初期データとしていくつかのTodoをstateへ設定 32 // 初期データを設定、TodosStateLoadingからTodoStateDataへ変わるのでローディング完了の状態となる 33 var prefs = await SharedPreferences.getInstance(); 34 35 final todosJson = prefs.getString('todos'); 36 final todos = json.decode(todosJson).map<Todo>((json) => Todo.fromJson(json)).toList(); 37 38 if (todos == null) { 39 state = TodosStateData( 40 todos: [ 41 Todo(id: _uuid.v4(),title: 'テスト'), 42 ] 43 ); 44 } 45 state = TodosState( 46 todos: todos 47 ); 48 } 49 50 51 52 53// [ Todo(id: _uuid.v4(), title: 'テスト'), 54 55 void add(String title) async {//追加機能 56 final SharedPreferences prefs = await SharedPreferences.getInstance(); 57 final currentState = state; 58 if (currentState is TodosStateData) { 59 // todosのクローンに新しいTodoを追加してstateを更新 60 final todos = currentState.todos.toList() 61 ..add( 62 Todo(id: _uuid.v4(), title: title), 63 ); 64 65 final todosJson = json.encode(todos); 66 prefs.setString('todos', todosJson); 67 68 state = currentState.copyWith(//stateはimmutableでメンバ変数を直接変更することはできないので、stateを更新するときは現在のstateからcopyWithでコピーするか、新規のstateで上書きする 69 todos: todos, 70 ); 71 72 } 73 } 74 75 void toggle(Todo todo) {//未完了/完了 76 final currentState = state; 77 if (currentState is TodosStateData) { 78 // Todoを検索してcomplatedをtoggleし、stateを更新 79 final todos = currentState.todos.map((t) { 80 if (t == todo) {//map()与えられた各要素に処理を掛けた後に、その要素群に対する新しいリストを作成する。 81 return t.copyWith( 82 completed: !t.completed, 83 ); 84 } 85 return t; 86 }).toList(); 87 state = TodosState( 88 todos: todos, 89 ); 90 } 91 } 92} 93
試したこと
エラーメッセージから読み取ると起動時にnullの時の処理がないから、起動しないのかなと思い
nullの場合を実装しましたがうまくいきませんでしt。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
あなたの回答
tips
プレビュー