本エントリではprovider
を用いた状態管理を以下の流れで説明する。
状態管理とは
本エントリで状態管理とはアプリケーション内の変数の値をどのように保存・更新・読み取り・削除するかを指す。
アプリ開発を進めると徐々にコードの規模が大きくなる。 その際に状態管理を適当に行っていると、「この時にアプリは何を表示している?」「この変数はいつ値が変更される?」などの問題が発生し保守性や開発効率の低下を引き起こす。
そのため効率的にアプリ開発を行う上で状態管理は必須になる。
providerとは
概要
provider
はウィジェットツリー上の子ウィジェットに状態変化を通知するためのパッケージ。
Flutterにおいて状態管理を行うためのツールとしてはかなりメジャーで実際の開発現場でも頻繁に使用されるため是非慣れておきたい。
InheritedWidget
をラップしたパッケージで、変化した状態に応じて必要なウィジェットのみをリビルトすることができる。
Flutter公式サイトのcookbookにもprovider
の利用方法を説明したページがあるので適宜参照してほしい。
使用方法
データの準備
provider
で管理するデータはChangeNotifier
を継承したクラスを作成する。
例として以下のような記述になる。
ポイントは
- データ用クラスは
ChangeNotifier
を継承する - 変数の値を変更後に
notifyListeners()
をコールする
の2点。
データの共有
「データの準備」で作成したクラスは
MultiProvider
ChangeNotifierProvider
を用いることでchildプロパティに指定した子ウィジェットに共有することができる。
具体的には以下のように記述する。
データの取得
データを取得する際には以下を利用する。
context.watch<T>()
context.read<T>()
context.select<T>()
各メソッドの違いは以下。
メソッド名 | 説明 |
---|---|
context.watch<T>() |
Tのデータを取得と監視。notifyListeners() によって変更が通知される |
context.read<T>() |
Tのデータを取得のみ。notifyListeners() によって変更は通知されない |
context.select<T>() |
Tのデータで指定したプロパティのみ取得と監視。notifyListeners() によって変更が通知される |
context.select<T>()
はTのプロパティの一部のみ変更を受け取りたい場合に用いる。
そのため再ビルドの回数を抑えてアプリのパフォーマンスを上たい場合に使用する。
サンプルアプリ
provider
を用いたシンプルなTodoアプリを作成する。
動作
コード
コードは分量が多いため以下のリポジトリを参照。 興味があればcloneして実際に操作をしていただきたい。
解説
フォルダ構成
フォルダは以下の構成。
各ファイルの役割を簡単に説明する。
ファイル名 | 役割 |
---|---|
main.dart | アプリのエントリーポイント |
todo_model.dart | Todo アイテム用のモデル |
todo_provider.dart | 表示するTodo インスタンス一覧の管理用provider |
home_page.dart | Todo インスタンス一覧を表示するためのページ作成用 |
create_page.dart | Todo インスタンス作成ページ用 |
list_item.dart | home_page.dartで各Todo インスタンスを表示するためのウィジェット作成用 |
ポイント
本サンプルアプリはprovider
を用いて
の機能を実装している。一つずつ詳細に解説する。
Todoインスタンスの共有
ウィジェットツリーにてHomePage
以下のウィジェットに対してTodo
インスタンスを共有するため、MultiProvider
でHomePage
をラップする。
Todoインスタンスの一覧への追加
Todo
インスタンスを一覧に追加するためにaddTodo()
メソッドを作成した。
_todos.add(todo)
でTodoProvider
で管理しているTodo
インスタンス一覧に追加を行い、その後notifyListeners()
で変更の通知を行っている。
Todoインスタンス一覧の取得
Todo
インスタンス一覧の取得はhome_page.dart
、list_item.dart
で以下のように行っている。
変更を監視したいので、context.watch<TodoProvider>()
で一覧を取得している。
Todoインスタンスの一覧からの削除
Todo
インスタンスを一覧から削除するためremoveTodoAtIndex(int index)
メソッドを作成。
削除の際には_todos
リスト上のインデックスが必要なので引数で取得する。
リストから対象のTodo
インスタンスを削除後、notifyListeners()
で変更の通知を行っている。
removeTodoAtIndex(int index)
メソッドは以下のように使用している。
Todoインスタンスの更新
一覧上のTodo
インスタンスを更新するためupdateIsDoneAtIndex(int index)
メソッドを作成。
サンプルアプリではisDone
プロパティのみ更新する。
更新の際には_todos
リスト上のインデックスが必要なので引数で取得する。
プロパティを更新後notifyListeners()
で変更の通知を行っている。
updateIsDoneAtIndex(int index)
メソッドは以下のように使用している。