.
├── analysis_options.yaml // lint
├── lib
│ ├── app.dart
│ ├── main.dart // ProviderScopeでラップ
│ ├── model
│ │ ├── api.dart
│ │ ├── controllers
│ │ │ ├── xxx_controller
│ │ │ │ ├── xxx_controller.dart
│ │ │ │ │ // StateNotifierとProviderを定義(controllers.dartで一括exportのためstateのexport)
│ │ │ │ │ // stateの変更系メソッド定義
│ │ │ │ ├── xxx_state.dart
│ │ │ │ │ // controllerにセットするstateを定義
│ │ │ │ │ // 表示に使用するフィールド定義(ソート済リストやフォーマット文字列など('合計${xxx.total}'))
│ │ │ │ └── xxx_state.freezed.dart
│ │ │ └── controllers.dart // controllers配下のcontrollerをexport
│ │ ├── entities // APIやDBなど外部リソースから取得したJSONデータなどをマッピングさせるオブジェクト
│ │ │ ├── xxx
│ │ │ │ ├── xxx.dart // ※1
│ │ │ │ └── xxx.freezed.dart
│ │ │ └── entities.dart // 各entityをexport(他のentityのimportが../entities.dartでできる)
│ │ └── model.dart // entities.dart, controllers.dartをexport
│ ├── pages // 画面単位で分割
│ │ └── xxx_page
│ │ ├── xxx_button.dart
│ │ ├── xxx_page.dart
│ │ └── tile
│ │ ├── xxx_tile.dart
│ │ ├── xxx_tile_controller.dart
│ │ │ // local使用のStateNotifier, xxx_tileのみで使用するのでProviderで外部公開しない
│ │ ├── xxx_tile_state.dart // local使用のstate
│ │ └── xxx_tile_state.freezed.dart
│ ├── providers
│ │ ├── navigator.dart // ※2
│ │ └── providers.dart // navigator.dartをexport
│ ├── util
│ │ └── logger.dart
│ └── widgets // 共通widget
│ ├── xxx_image.dart
│ ├── xxx_info.dart
│ ├── navigation_bar_button.dart
│ └── widgets.dart // 'package:flutter/material.dart'と各widgetsをexport
└── test
├── helper
│ └── dummy_xxx.dart // モックデータ
├── model
│ ├── api_test.dart
│ ├── controllers
│ │ └── xxx_controller_test.dart
│ └── entities
│ └── xxx.dart
├── pages
│ └── xxx_page
│ └── xxx_tile_controller_test.dart
└── smoke_test.dart
※1
- fromJsonコンストラクタでjson => オブジェクト生成
@freezed
abstract class xxx with _$xxx {
factory xxx({
required int id,
required int price,
required String title,
required String imageUrl,
}) = _xxx;
xxx._(); // private constructor https://stackoverflow.com/questions/55143244/is-it-possible-to-have-a-private-constructor-in-dart
factory xxx.fromJson(Map<String, dynamic> json) => _$xxxFromJson(json);
}
※2
import 'package:flutter/widgets.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
final navigatorKeyProvider = Provider((_) => GlobalKey<NavigatorState>());
extension NavigatorStateEx on NavigatorState {
BuildContext get descendantContext => overlay!.context;
}
- navigatorKeyProviderをMaterialAppのnavigatorkeyに差し込むことでどこでも画面遷移可能になる
class MyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
final navigatorKey = watch(navigatorKeyProvider);
// return widgets
onTap: () {
navigatorKey.currentState.pushNamed("foo");
}
- NavigatorStateEx
- Navigator.of()でNavigatorStateを取れるcontext得るために、NavigatorStateのoverlay.contextを渡すために使用
navigatorKey.currentState.descendantContext; // get BuildContext
monoさんありがとうございます!!!