Scoped Model を利用した場合の画面遷移でうまくいったコード例（Flutter）

最近Flutterをいじり始めました。Scoped Modelを利用するとスッキリ書けるので、そのコードを書いたときの画面遷移時に具体的にどうコードを書くとうまくいったかをレポートします。

# [Scoped Model 初めて聞いた方へ]Scoped Model　とは

公式のパッケージサイトは下記です。

https://pub.dev/packages/scoped_model


基礎原理の解説について下記記事が参考になりました。

https://qiita.com/hayassh/items/690fa0d6528e056617b5

自分の言葉で書くと、数値や文字列の処理部分とデザインテンプレート部分をModel定義をすることで綺麗に分離ができます。あと、このパッケージは、GoogleのFlutter開発チームが提供してくれているVeggie Seasonsというアプリのコードにも採用されていたので、自分もやってみようと思いました。Veggie Seasonsのコードは以下です。

https://github.com/flutter/samples/tree/master/veggieseasons

# ページ遷移時の試行錯誤時のエラー解決で得た知見

今回はこちらを共有したいのです。Scoped Modelを使わない場合と比較できるように書いてみました。

```#main.dart

//1:route定義をMaterialAppのところで行って、

void main() {

  runApp(MaterialApp(
    title: 'Demo',
    initialRoute: '/',
    routes: {
      '/': (context) => FirstScreen(),
      '/second': (context) => SecondScreen(),
    },
  ));
}

//2:↓最初のページに当たるFirstScreen部分のStatelessWidget記述です。

class FirstScreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: Text('Demo'),
      ),
      body: Center(

      // 中略
      child: RaisedButton(
          padding: EdgeInsets.all(12.0),
          shape: StadiumBorder(),
          child: Text(
            "次のページへ",
            style: TextStyle(fontSize: 20.0, color: Colors.white),
          ),
          color: Colors.green,
          onPressed: () {

            Navigator.pushNamed(context, "/second");
            //3:↑で次のページ"SecondScreen()"へ移動クラス生成です。
          },
        ),

//次の画面(SecondScreen)
class SecondScreen extends StatelessWidget {

   //以下略SecondScreenの表示内容などが書かれています。

}
```

↑これをScoped Model 活用して記述する際、
下記のように書くとうまくいきました。　　

```#main.dart
import 'model.dart'; 
/*
↑model（今回はDemoModelという名称です）を別ファイルで定義しました。
このmodelそのものの部分の解説は、
ページ遷移の解説に戻るまでにかなり時間がかかるので割愛します。
※本記事前述の解説などの参考になる記事が複数存在しますので、ご覧ください。
*/

import 'package:scoped_model/scoped_model.dart';
// scoped_modelのパッケージをインポートします。

DemoModel demoModel = DemoModel();
//modelを生成しておきます。

void main() {

  runApp(MaterialApp(
    title: 'Demo',
    home: ScopedModel<DemoModel>(
        model: demoModel,
        child: new FirstScreen()
    )
  ));
}

/*
route指示部分がごっそり無くなっています。書いてみるとエラーになりました。
遷移時に各ボタンなどの実行時のコードに
Scoped Modelの子孫のクラスとなる次のページのクラス生成を指示することになります。
*/

//最初の画面(FirstScreen)
class FirstScreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: Text('Demo'),
      ),
      body: Center(

      // 中略
      child: RaisedButton(
          padding: EdgeInsets.all(12.0),
          shape: StadiumBorder(),
          child: Text(
            "次のページへ",
            style: TextStyle(fontSize: 20.0, color: Colors.white),
          ),
          color: Colors.green,
          onPressed: () {

            

            Navigator.push(
              context,
              new MaterialPageRoute<Null>(
                settings: const RouteSettings(name: "/second"),
                builder: (BuildContext context) {
                    return MaterialApp(
                      home: ScopedModel<DemoModel>(
                        model: quizBrainModel,
                        child: new SecondScreen(),
                      ),
                    );
                  }
              ),
            );

            /*
            ↑ScopedModelを使わない場合、
            Navigator.pushNamed(context, "/second");となっていた部分です。
            */

          },
        ),

//次の画面(SecondScreen)
class SecondScreen extends StatelessWidget {

  SecondScreen();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: Text("Second Page"),
      ),
      body: 
      
      //中略
      
      new ScopedModelDescendant<DemoModel>(
         builder: (context, child, model) =>
         new Row( children: model.getSomeList())
     )

     /*
     ↑このページは、Scoped Model子孫クラスなので
     new ScopedModelDescendant<Model名称>で
     メソッドや変数が呼び出せます。
     例としてmodelで指定しておいた、
     特定のListを呼び出すメソッドを書いています。
     */

```

参考になればと思います。他にも書き方があるかもしれません。ご指摘などあればコメントいただければと思います。