【初心者】Flutter:APIでデータ取得して、一覧表示させるサンプルアプリ

# はじめに
FlutterでAPIからデータ取得して、リスト表示するサンプルを作成しました。
[FlutterでAPIをコールしてデータを表示して見た](https://dev.classmethod.jp/smartphone/flutter_api_call_1/)
この記事見て、自分もFlutterで同様のやつを作成したかったので、
いろいろ調べた結果をQiitaにのっけときます。

# 今回つくるもの
<details>
![Screenshot_20181014-015712 (3).png](https://qiita-image-store.s3.amazonaws.com/0/190712/b04ef3da-673f-2c3b-cb0e-a0ce24564ac3.png)!

</details>

初心者向けに（自分もflutter初心者なので）段階を追ってかきたい。

# つくろう
### 1.必要モジュールのインポート
```dart:main.dart
import 'package:flutter/material.dart'; //google提供のUIデザイン
import 'package:http/http.dart' as http; //httpリクエスト用
import 'dart:async'; //非同期処理用
import 'dart:convert'; //httpレスポンスをJSON形式に変換用
```
<details><summary>モジュールについて</summary>
[material.dart](https://docs.flutter.io/flutter/material/material-library.html)
Google公式のデザインパッケージ。flutterプロジェクト基本いれる。
[http.dart](https://pub.dartlang.org/packages/http)
HTTPリクエスト用.公式ドキュメントでも as httpとして使用してい。
[async](https://www.dartlang.org/articles/language/await-async)
JavaScriptのPromise。SwiftのSwiftTask。非同期処理
[convert](https://api.dartlang.org/stable/2.0.0/dart-convert/dart-convert-library.html)
Jsonのエンコーダー、デコーダー。
</details>

### 2.メイン関数のとアプリのひな型を作る
```dart:
void main() { // main.dartは基本これだけを呼ぶ
  runApp(MaterialApp( // runAppにはStatelessWidget or StatefullWidgetを継承したものを渡す
    home: HomePage(),  //homeで、ルーティング情報ここにかいてく。
  ));
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(); //Scaffold() アプリの中身（appbar+title構造）を簡単につくれる
  }
}
```
<details><summary>メイン関数とその後の動きについて</summary>
run main.dart
-> main()　-> runApp()　-> home: 
-> (state情報みる)HomePage -> （state継承した）_HomePageState()
-> build() (Widgetはbuild()をもっている)
Dartの状態遷移は以下の記事参照
[Flutterアプリの基本](https://issus.me/projects/1520/issues/2)/[Flutterの状態遷移について](https://qiita.com/tatsu/items/38cd85efd93005b95af9)
Dartのstatefull,statelessについては以下参照
[statefull,statelessについて(日本語)](https://milestone-of-se.nesuke.com/nw-basic/as-nw-engineer/stateful-and-stateless/)/[statefull,statelessについて(英語)](https://stackoverflow.com/questions/47501710/what-is-the-relation-between-stateful-and-stateless-widgets-in-flutter)
状態変化に応じて変わるor変わらないこと。
上記のふるまいがアプリ起動時の基本形でありひな型部分。
Widget build()の内部にゴリゴリとデザインとアクションを書き込んでいくこと。
Scaffold()が簡単に書くために用意されてるのでつかう。
</details>

### 3.タイトルバーと背景色つける
```dart
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("あああああ"),
        backgroundColor: Colors.green,
      ),
    );
  }
```
<details><summary>Scaffold,appBarについて</summary>
[Scaffold_class](https://docs.flutter.io/flutter/material/Scaffold-class.html)
[Scaffold_samples](https://flutter.io/catalog/samples/Scaffold_index/)
class:Implements the basic material design visual layout structure.
description:A typical AppBar with a title, actions, and an overflow dropdown menu.
scaffold()は、バー、タイトル、中身、アクション、ボトムの典型的なアプリ構造を簡単にできる仕組みらしい。詳しくはSamplesリンクをみるとわかります。
[appBar](https://flutter.io/catalog/samples/basic-app-bar/)
![basic_app_bar_small.png](https://qiita-image-store.s3.amazonaws.com/0/190712/fa798028-19a1-a423-5990-410cee9522e5.png)
タイトル、ボタンとかをおく。ボタンには（画像みたいに）アクションとか置いてくのが典型的な仕組み。
今回は置かないで、テキストと背景色をつけるだけ。

</deitals>
### 3.2ここまででできるやつ
<details>
![Screenshot_20181014-015712 (4).png](https://qiita-image-store.s3.amazonaws.com/0/190712/1169b116-6f1c-3d9a-4df2-9af2faade58c.png)
</details>

### 4.APIデータを用意する
どこでもいいですが、サンプルページ[REQ | RES](https://reqres.in/)にある、
以下のデータをつかわせていただく。

```json
{
    "page": 2,
    "per_page": 3,
    "total": 12,
    "total_pages": 4,
    "data": [
        {
            "id": 4,
            "first_name": "Eve",
            "last_name": "Holt",
            "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/marcoramires/128.jpg"
        },
        {
            "id": 5,
            "first_name": "Charles",
            "last_name": "Morris",
            "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/stephenmoon/128.jpg"
        },
        {
            "id": 6,
            "first_name": "Tracey",
            "last_name": "Ramos",
            "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/bigmancho/128.jpg"
        }
    ]
}
```

使用するurlは以下です。

```url:url_for_request
https://reqres.in/api/users?page=2
```
### 5.非同期操作とか
```dart
//class _HomePageState extends State<HomePage> {

  Future getData() async{ //Future xxx async{} という記法
    http.Responsde response = await http.get("https://reqres.in/api/users?page=2");
  }  
  // 非同期処理は、デフォルトでは呼び出し元は処理の完了を待ちませんが、
  // await キーワードをつけると完了を待つことができる。
  @override
  void initState() {
    super.initState();
    getData();
  }
```
<details>
[async_公式](https://www.dartlang.org/tutorials/language/futures)/[async_日本語](https://blog.chocolapod.net/momokan/entry/104)
非同期処理:処理が呼び出されつつも、呼び出し元では完了を待たずにその先に処理が進んでいくこと。
[initState_method](https://docs.flutter.io/flutter/widgets/State/initState.html)/[widget lifecycle events](https://flutter.io/widgets-intro/#responding-to-widget-lifecycle-events)
initStateは、viewのライフライクル的に言えば、Stateオブジェクトがつくられてから"一度"呼ばれるらしい。
呼ばれるタイミングと頻度は重要。ライフサイクルは要復習。
</details>

### 6.データ変換:JSON->Map and List
```dart
//class _HomePageState extends State<HomePage> {

  Map data;
  List useData;

//  Future getData() async{
//    http.Responsde response = await http.get("");
    data = json.decode(response.body); //json->Mapオブジェクトに格納
    setState(() { //状態が変化した場合によばれる
      userData = data["data"]; //Map->Listに必要な情報だけ格納
    });
  }
```
<details>
[Flutterアプリの基本](https://issus.me/projects/1520/issues/2)/[FlutterのStateについて](http://mashi.exciton.jp/archives/268)
変数を用意して、取得したデータを順次処理していく段階。
json->Map->List。
</details>

### 7.1 画面に表示させる-プロフィール画像
```dart
//      appBar: AppBar(
//        title: Text("あああああああ"),
//        backgroundColor: Colors.green,
//      ),
      body: ListView.builder( //スクロール可能な可変リストを作る
          itemCount: userData == null ? 0 : userData.length, //受け取る数の定義
          itemBuilder: (BuildContext context, int index) { //ここに表示したい内容をindexに応じて
            return Card( //cardデザインを定義:material_design
              child: Row(
                children: <Widget>[
                  CircleAvatar( //ユーザプロフィール画像に使う用のクラス
                    backgroundImage: NetworkImage(userData[index]["avator"]),
                    //NetworkImage()はHTTPで画像をとってくる。これはプロフィール画像。
                  )
                ],
              ),
            );
          },
      )
```
<details>
[ListView.builder_const](https://docs.flutter.io/flutter/widgets/ListView/ListView.builder.html)/[リストを表示する](https://nzigen.com/flutter-reference/2018-04-17-list-view.html)
ListView.builder:countとbuilderで、値の数だけ柔軟に生成できるリスト構造
[Flutterでよくつかう共通Widget
](https://qiita.com/konifar/items/1136dd1d69ed0895b6d5)/[Card_class](https://docs.flutter.io/flutter/material/Card-class.html)
card:以下のような、よく使われる共通デザインのこと。
![card.png](https://qiita-image-store.s3.amazonaws.com/0/190712/fc9370b8-100b-98d3-5fbe-b5c237441caa.png)
[CircleAvator_class](https://docs.flutter.io/flutter/material/CircleAvatar-class.html)/[githubアプリ](https://qiita.com/rkowase/items/56f6606b7e101d939e10)
CircleAvator->NetworkImageというプロフィール画像を表示するテンプレの実装
</details>
### 7.2 画面に表示させる-テキスト
```dart
//                   CircleAvatar(
//                      backgroundImage: NetworkImage(userData[index]["avator"]),
//                    ),
                    Text("${userData[index]["first_name"]} ${userData[index]["last_name"]}")
```

あとはpaddingとかをちょうせつしたら完成します！

# あとがき
flutterは公式ドキュメントがかなり充実しているので大助かり。
あと、英語力がないと積むのだけ注意。