..

Flutter 2.5 スケルトンをながめる(3)

前回 の続き。 Flutter2.5からスケルトンが提供されるようになったので、それをながめてみる。

5. sample_feature

sample_featureディレクトリをながめる。このディレクトリには3つのファイルが含まれている。
サフィックスが_viewとなっている2つが画面、あとの1つはモデルである。つまり、sample機能をもつモデルとその一覧画面および詳細画面を、ひとつのディレクトリに置くという方針である。

└── src
    ├── sample_feature
    │   ├── sample_item.dart
    │   ├── sample_item_details_view.dart
    │   └── sample_item_list_view.dart

参考 【Flutter】悩ましいフォルダ構成について語り合おう

5.1. SampleItem

SampleItemはモデルクラスで、コンストラクタでidプロパティをセットしているのみである。

5.2. SampleItemListView

まず、コンストラクタで、itemsにSampleItemのリストを設定している。

つぎに、以下のように画面遷移のためのrouteNameを設定している(4.3. 画面遷移(ルート)を参照)。

static const routeName = '/';

最後に、build関数で画面を生成している。

appBarには、actionsにIconButtonをおき、SettingsView画面への遷移を可能にしている

bodyには、ListViewをおき、items(SampleItemのリスト)を表示している。 itemの表示にはListTileをつかい、タップするとSampleItemDetialsView画面へ遷移する。

そして、このListViewには、restorationIdが設定されている。これを指定することで、アプリケーションが長時間バックグランドで実行されていたためにkillされたあと、再び利用を開始するときにスクロールの位置を復元できる。実際に、itemsの数を増やして試すと、スクロール位置が復元された。すごい。

restorationId: 'sampleItemListView';

restorationId property

先の記事、4.1. restorationScopeIdにあった「ルートの復元可能な状態」とは、このようなことなのか。

5.3. SampleItemDetialsView

まず、画面遷移のためのrouteNameを設定している。

あとは、build関数で画面を生成している。といっても中身は、appBarには画面タイトル、bodyには固定テキストだけである。 せめて、一覧画面で選んだitemくらいは表示してもいいだろう。

5.4. 改造

ということで、一覧画面で選んだitemを、詳細画面で表示してみる。

まず、画面遷移のときに値を渡すように変更する。

app.dart

onGenerateRoute: (RouteSettings routeSettings) {
  final args = routeSettings.arguments; // 追加した。
  return MaterialPageRoute<void>(
    settings: routeSettings,
    builder: (BuildContext context) {
      switch (routeSettings.name) {
...
        case SampleItemDetailsView.routeName:
          return SampleItemDetailsView(args: args); // 引数を追加。引数により表示内容がかわるので、constは削除。

遷移時には、itemのidを渡すようにする。

sample_item_details_view.dart

Navigator.restorablePushNamed(
  context,
  SampleItemDetailsView.routeName,
  arguments: {'itemid': item.id},  // 追加した。
);

詳細画面では、コンストラクタに引数を追加して、

sample_item_details_view.dart

const SampleItemDetailsView({Key? key, this.args}) : super(key: key);
final Object? args;

build関数内で、表示してみる。

sample_item_details_view.dart

  @override
  Widget build(BuildContext context) {
    final item = args as Map;    // 追加
    final itemid = item["itemid"]; // 追加
    return Scaffold(
...
      body: Center( // constを削除
        child: Text('More Information Here : item.id = $itemid'), // item.idを表示するように
      ),

これで動作確認ができた。 sample_item_details_view.dartに追加した2行はもっとスマートに書けそう。 本来なら、チェックのロジックが必要なところだろうが。