サンプルアプリの概要
今回、使用するサンプルアプリは図1のようなアプリです。画面は3つありますが、すべて同じ画面であり、また、そのふるまいも同じです。
ただし、以下のように3つのアーキテクチャを使って実装します。それらの違いについて、アーキテクチャの構造とコード面から違いを見てほしいと思います。
- Stateのみを用いる方法
- 変更(イベント)通知(ProviderとChangeNotifier/Consumer)を用いる方法
- BLoCパターン(ProviderとStreamController/StreamBuilder)を用いる方法
Stateのみを用いる方法
この方法はアーキテクチャと呼べるかわかりませんが、最も基本となる知識のみを使って実装する方法です。後で紹介する他の2つの方法と比べて、どこが変わるかを知っていただくために最初に紹介します。
また、このコードの構造を簡易的に示したのが図2です。
class _SimpleScreen extends State<SimpleScreen>{ // (1) Stateで管理する変数 bool _loading = true; List<DateItem> _week = []; @override void initState() { super.initState(); // (2) 初期化時にデータをロード _loadData(); } // (3) データをロードする処理 void _loadData() async{ var res = await http.get(Uri.parse("http://192.168.1.1/list.json"),headers: { 'Accept' : 'application/json' }); setState(() { var json = jsonDecode(utf8.decode(res.bodyBytes)); _loading = false; _week = json['items'].map<DateItem>((e) => DateItem.fromJson(e)).toList(); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('サンプル(1)'), actions: [ // (4) リロード処理 IconButton(onPressed: _loading? null :(){ setState(() { _loading = true; }); _loadData(); }, icon: const Icon(Icons.refresh)) ], ), // (5) 画面の表示 body: Stack( children: [ Column( children : _createListChildren(context), ), if(_loading) loadingWidget(context) ] ), ); } // (6) Loading 画面を表示 Widget loadingWidget(BuildContext context){ return Container( : (省略) ); } // (7) 5日分のColumnを表示 Widget listWidget(BuildContext context){ return Center( child: Column( children : _createListChildren(context) ), ); } List<Widget> _createListChildren(BuildContext context){ var _list = <Widget>[]; for(var i = 0; i < _week.length; i++){ DateItem item = _week[i]; // (8) 週(月〜金)の1日を表示するウィジェット _list.add(DateBlock(item: item)); } return _list; } } class SimpleScreen extends StatefulWidget{ // : (省略) }
(1)がState管理する変数です。この変数の値が変わったら画面が更新されます。画面が最初に作成されるタイミングでデータを取得しなければならないので、(2)のinitState()メソッドで(3)のようにデータを取得します。
また、(4)ではリロードボタンを押されたタイミングでも再度データを取得します。画面表示(5)では、Stackを用いてローディング表示を通常の画面の上に置くようにしています。
(6)がローディング画面の実装、(7)が5日分を縦に並べたColumn表示をしています。そして(8)が1日分の表示処理です。この(6)〜(8)までの処理は今回の内容とはあまり関係がなく、このプログラムの重要な点は(2)の_loadData()メソッドになります。
各画面部品を表示する実装はこの後紹介する方法でも、ほぼ同様のため、このコードと違うところに着目して、他のコードを見るようにしてください。