今回はFlutter の状態を扱う機能であるState クラスについて勉強します。
これまで書いてきた StateクラスはStatelessWidget(静的クラス)でした。
Flutter のState は2種類存在します。
- StatelessWidget (静的なState)
- StatefulWidget (動的なState)
よくFlutter の基本的なソースコードである
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
String title = 'Flutter のテストアプリ';
String message = 'Hello World, Flutter';
@override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
);
}
}
で使われるときがStatelessWidget で考えるような感じです。
それに対して変数によって値を変えたいときに使うウィジェットの場合にはStatefulなウィジェットを継承させてクラスを作成します。
StatefulWidget の基本形な次のとおりです。
// ウィジェット
class AWidget extends StatefulWidget {
_AWidgetState createState() => new _AWidgetState();
}
// 状態を持つクラス
class _AWidgetState extends State<AWidget> {
@override
Widget build(BuildContext context) {
}
}
と2つのクラスを作成しなければいけない感じです。
この基本形は丸暗記すればよさそう。
このStatefulWidgetを使ったサンプルコードを下に記載します。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
String title = 'Flutter のテストアプリ';
String message = 'Hello World, Flutter';
@override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter App',
home: new SamplePage(
title: this.title,
message: this.message,
),
);
}
}
// ウィジェット
class SamplePage extends StatefulWidget {
String title;
String message;
SamplePage({this.title, this.message}): super();
_SamplePageState createState() => new _SamplePageState();
}
// 状態を持つクラス
class _SamplePageState extends State<SamplePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.message),
),
body: Text(widget.message,
style: TextStyle(fontSize: 32.0),
),
);
}
}
ぱっと見ではネストが深いイメージがあります。
これが最小単位でビルドすると下のスクリーンショットの画像が表示されます。
StatefulWidgetを使った最小コード
Widgetクラスで別ファイルに切り分ける
本当はこのまま下にStateクラスを作成して入れ子に組み込んでいけばレイアウトができてくるのですが、
私の場合まだ慣れないのでここでSamplePage
を別ファイルに分離して切り分けたいと思います。
Flutter の場合、新しいDartファイルを作成してそこに移動させたらいいみたいです。
このようにlib
ディレクトリの中に新しいdartクラスsample_widget
ファイルを作成しました。
このsample_widget のファイルに下のソースコードを書きます。
import 'package:flutter/material.dart';
// ウィジェット
class SamplePage extends StatefulWidget {
String title;
String message;
SamplePage({this.title, this.message}): super();
_SamplePageState createState() => new _SamplePageState();
}
// 状態を持つクラス
class _SamplePageState extends State<SamplePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.message),
),
body: Text(widget.message,
style: TextStyle(fontSize: 32.0),
),
);
}
}
そして、main.dart のファイルを次のように編集します。
といっても、sample_widget
ファイルを読み込むためにimport しただけです。
import 'package:flutter/material.dart';
import 'package:practice_app/sample_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
String title = 'Flutter のテストアプリ';
String message = 'Hello World, Flutter';
@override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter App',
home: new SamplePage(
title: this.title,
message: this.message,
),
);
}
}
これで作成したStatefulWidget を別ファイルからimportして使えるようになりました。
まだFlutte 触りだして1週間ですのでクラス名も分離の基準もこれで正しいか分かりません。
ですが、これでUIと画面を分離できたかなと思います。
Stateのプロパティにアクセスするwidgetプロパティ
ここで説明を省略しましたが、Stateクラスで使われているwidget
というものがあります。
widget.title
とかwidget.message
と書かれている箇所です。
widget
とはStateクラスに用意されているプロパティで_SamplePageState
そのものを指します。
import 'package:flutter/material.dart';
// 状態を持つクラス
class _SamplePageState extends State<SamplePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.message),
),
body: Text(widget.message,
style: TextStyle(fontSize: 32.0),
),
);
}
}
簡単に言えば、Stateを継承しているのでこのStateを継承することで
widget プロパティ(つまり、this)にアクセスできる仕様なんだと思います。
とりあえず納得するしかありません。
これでだいたいStateについて学べたかと思います。