虎視眈々と

Flutter × Firebaseを研究するアプリエンジニア

FlutterからAPIを叩いて結果を受け取る

FlutterからAPIを叩いて結果を受け取る

FlutterからAPIを叩いてjsonを受け取るまで処理を書いていきます。

サンプルコードはこちらになりますので合わせてご確認ください。

github.com

APIクライアントを書く

一般的にAPI叩くときはこんな感じだと思います。

  1. http GET
  2. json parce
  3. オブジェクトにして返す

Flutterでは async await が使えるのでスマートかけていい感じです。

http GET

URLを叩いてる実装はこんな感じ

Future<List<ScheduleModel>> getItems() async {
    final result = await client.get("叩くAPIのURL");
    final json = (await jsonDecode(result.body)) as List<dynamic>;
    final list = json.map((j) => ScheduleModel.fromJson(j as Map<String, dynamic>)).toList();
    return list;
  }

APIを叩いてから結果を受け取りjsonDecodeしています。

ScheduleModel.fromJsonjsonをパースしています。

json parce

class ScheduleModel {

  String title;
  int time;
  String tag;
  String hour;

  ScheduleModel.fromJson(Map<String, dynamic> json)
      : title = json['title'] as String,
        time = json['time'] as int,
        tag = json['tag'] as String,
        hour = json['hour'] as String;
}

実際にパースするのはjsonの構造に適宜変えてください。

オブジェクトにして返す

これでオブジェクトにしてコールバックするので今度は呼び側を実装していきます。 今回のサンプルコードではBlocパターンを使って実装しているのでBlocのsink経由で取得します。


import 'dart:async';
import 'package:bloc_sample_app/BlocProvider.dart';
import 'package:bloc_sample_app/Schedule/ApiClient.dart';
import 'package:bloc_sample_app/Schedule/ScheduleModel.dart';

class ApiBloc implements BlocBase {

  StreamController<List<ScheduleModel>> _scheduleController = StreamController<List<ScheduleModel>>();
  StreamSink<List<ScheduleModel>> get items => _scheduleController.sink;
  Stream<List<ScheduleModel>> get outStream => _scheduleController.stream;

  ApiBloc() {

    _getItems();
  }

  @override
  void dispose() {
    _scheduleController.close();
  }

  void _getItems() async {
    final itemList = await ScheduleClient().getItems();
    _scheduleController.sink.add(itemList);
  }
}

_getItems() でメソッドでAPIを叩いてデータを取得しています。 取得したデータはsinkにaddすることでStreamが反応します。

  • View
import 'package:bloc_sample_app/BlocProvider.dart';
import 'package:bloc_sample_app/Schedule/ScheduleBloc.dart';
import 'package:bloc_sample_app/Schedule/ScheduleModel.dart';
import 'package:flutter/material.dart';

class ScheduleStateless extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider<ApiBloc>(
      bloc: ApiBloc(),
      child: Schedule(),
    );
  }
}

class Schedule extends StatefulWidget {
  @override
  _ScheduleState createState() => _ScheduleState();
}

class _ScheduleState extends State<Schedule> {
  @override
  Widget build(BuildContext context) {
    final ApiBloc bloc = BlocProvider.of<ApiBloc>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text("スケジュール"),
      ),
      body: StreamBuilder<List<ScheduleModel>>(
          stream: bloc.outStream,
          builder: (context, snapshot) {
            if (snapshot == null || snapshot.data == null) {
              return Center(
                  child: CircularProgressIndicator()
              );
            }
            return ListView.builder(itemBuilder: (context, position) {
              var item = snapshot.data[position];
              return _listItems(item);
            });
          }),
    );
  }

  Widget _listItems(ScheduleModel item) {
    return Card(
      child: ListTile(
        title: Text(item.title),
        subtitle: Text(item.hour),
        trailing: Text(item.time.toString() + "時間"),
      ),
    );
  }
}

StreamBuilder クラスを使って画面にデータを取得しています。

最後に

サンプルコードは下記においたので合わせてご覧ください

github.com

Blocパターンについても記事に書いたのでこちらもどうぞ。

www.shogogeek.com