【スクラップ】Flutterの勉強
アプリ作りで学んだFlutterについての知見を殴り書きする。
基本
重要な用語がWidget, Route, スタック。
Widget
- 画面の構成要素(UIパーツ)。
- 木構造(Widgetツリー)を作って画面を表現する。
- ボタンやテキストのような小さなものから、Scaffoldのように画面全体を構成する大きなものまで含まれる。
Route
- 「1つの画面」に相当する概念。
- 内部に「その画面を描画するためのWidgetツリー」を持っている。
- 例:
MaterialPageRoute(builder: (context) => MemoListPage())
Navigator(スタック)
- Routeを管理する仕組み。
- スタック構造になっており、
push
→ 新しいRoute(画面)を追加pop
→ いまのRoute(画面)を削除
- スタックの一番上のRouteに対応するWidgetツリーが「表示中の画面」となる。
基本構成
MaterialApp と Navigator
- MaterialApp はアプリ全体のルートウィジェット
- Navigator は MaterialApp 内に配置される画面遷移の管理者
- 基本的に アプリごとに1つだけ(必要に応じてサブ Navigator を作る場合もある)
Route と Navigator の関係
- Route = 1つの画面
- すべての Route は 同じ Navigator のスタックに積まれる
- だから Route 内の context から
Navigator.of(context)
を呼べば、どの Route からでも同じ Navigator にアクセス可能
イメージ
MaterialApp
└─ Navigator
├─ Route(HomePage)
├─ Route(DetailPage)
└─ Route(SettingsPage)
- HomePage から Navigator.of(context) → Navigator に到達
- DetailPage から Navigator.of(context) → 同じ Navigator に到達
- Navigator のスタック上で push/pop すれば、表示画面が切り替わる
BuildContext
アプリ全体を表すウィジェットツリー内での自分の位置を指し示すハンドル。
ツリーの中で自分よりも親の情報を参照することができ、子の方向にはwidgetを作成することができる。
navigationKey
通常以下のような形でcontextをもとに画面遷移をする。
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => NextPage()),
);
Riverpod
Riverpod = Flutter で状態管理を便利に、安全に行うためのライブラリ
- 「状態管理」とは?
- 例えばカウンターの値、ログイン情報、アプリテーマ、APIから取得したデータなど
- Widget に直接値を持たせると管理が大変になることがある
- Riverpod を使うと 状態の保管場所(Provider)と使う場所(Widget)が分かれる
特徴
Widget から独立して状態を管理できる
- Widget が破棄されても Provider は生き続ける(必要に応じて再生成)
スコープを制御できる
- どの範囲の Widget に状態を渡すか自由に決められる
安全でテストがしやすい
- 依存関係を明示できる
古い Provider を簡単に置き換えられる
- DI(依存注入)的な使い方も可能
final counterProvider = StateProvider<int>((ref) => 0);
こんな感じで初期値設定には関数をパラメータとして渡す必要がある。理由は以下。
- Provider の初期値を 関数で渡す → 「必要になったときに初期値を計算できる」
- これにより以下が可能:
- 遅延初期化:アプリ起動時にすぐ計算されない
- 依存関係の参照:他の Provider の値を使って初期値を設定
- 柔軟な初期化ロジック:単なる定数以外の初期値も作れる
つまり「単純な 0 や空文字だけじゃなく、動的に初期値を決められるようにするため」に関数で初期化する仕組み
get
Flutter特有のシュガーシンタックス。get用のメソッドのようなものを簡単に作れる。作られたgetメソッドでは呼び出しも楽。
// 普通の関数
int getValue() => 42;
print(getValue()); // 呼び出すときは括弧が必要
// getter(シュガーシンタックス)
int get value => 42;
print(value); // 括弧なしでOK