Help us understand the problem. What is going on with this article?

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を呼び出すメソッドを書いています。
     */

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

k_mawa82
技術が色々好きです。開発会社Mules所属です。 よく使うものはDjango, Unity, ラズパイ, Flutterなど。
https://www.teammules.com/
mules
不動産業界2000店舗超の利用実績のあるMadoryサービスの開発・運用等、主に不動産業界向けアプリ・ソフトウェア開発運用などから社内サークルでの電子工作やxR技術まで、色々な技術チャレンジをしているチームです。電気通信事業届出番号 : A-01-17309
https://twitter.com/MulesTeamInfo
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした