search
LoginSignup
22
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

flutterアプリからAPIをPOSTで叩いてパラメータを渡す(サーバに保存する)

やりたいこと

  • アプリからPOSTでAPIを呼び出す。
  • POSTパラメータをJSONで渡して、API側で受け取ってサーバに保存する。
  • APIからのレスポンスメッセージをページに表示する。

image.png

上記「api success. This message from API.」は、APIからレスポンスしている文字列である。

前提

APIは任意の環境で作成済とする。
ここでは、PHPで自作したAPIを、下記URLでアクセスできるようにしてある(ローカルでのみ稼働。ネットには公開していない)。

http://172.16.0.223/creator/api/flutter_post_test

これをPOSTで呼び出す。API側では、渡されたパラメータをサーバのログに吐き出すようにしてあるので、
パラメータが確実に渡ったことをログで確認する。
IPアドレスは、自PCに起動したVirtualBox(仮想サーバ)のアドレスである。

APIのソース

今回はCakePHP3で実装した。id, name を受け取る。

    public function flutterPostTestApi()
    {
        $id = $this->request->getData('id') ?? null;
        $name = $this->request->getData('name') ?? null;
        if (empty($id)) {
            $this->badRequest('id is empty. This message from API.');
        }
        $response = [];
        $response['id'] = $id;
        $response['message'] = 'api success. This message from API.';
        $this->httpNormalResponse($response);
    }

[flutter] httpの許可

を参照。

[flutter] main.dart に リクエスト用のデータクラスを実装する。

下記クラスをnewする際に、
idとname(例えば、会員ID(数値)と会員名(文字列)を登録するようなAPIを想定)を、
コンストラクタで受け取ってメンバ変数に保持する。

class SampleRequest {
  final int id;
  final String name;
  SampleRequest({
    this.id,
    this.name,
  });
  Map<String, dynamic> toJson() => {
    'id': id,
    'name': name,
  };
}

[flutter] main.dart に APIを呼び出す処理を実装する。

APIに渡すパラメータは

id: 1234
name: 大和賢一郎

とした。

APIからは message が文字列で返ってくるので、
それを画面に表示させる処理も含める。 

Future<ApiResults> fetchApiResults() async {
  var url = "http://172.16.0.223/creator/api/flutter_post_test";
  var request = new SampleRequest(id: 1234, name: '大和賢一郎');
  final response = await http.post(url,
      body: json.encode(request.toJson()),
      headers: {"Content-Type": "application/json"});
  if (response.statusCode == 200) {
    return ApiResults.fromJson(json.decode(response.body));
  } else {
    throw Exception('Failed');
  }
}

[flutter] main.dart に APIからのレスポンスを受け取るデータクラスを実装する。

APIレスポンスの仕様に合わせて、受け取る変数を実装する。
今回は message を返すように実装した。

class ApiResults {
  final String message;
  ApiResults({
    this.message,
  });
  factory ApiResults.fromJson(Map<String, dynamic> json) {
    return ApiResults(
      message: json['message'],
    );
  }
}

[flutter] main.dart に画面表示などを実装する。

class _MyAppState extends State<MyApp> {
  Future<ApiResults> res;
  @override
  void initState() {
    super.initState();
    res = fetchApiResults();
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'APIをPOSTで呼び出しJSONパラメータを渡す',
      theme: ThemeData(
        primarySwatch: Colors.yellow,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Api JSON Post Sample'),
        ),
        body: Center(
          child: FutureBuilder<ApiResults>(
            future: res,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(
                  snapshot.data.message.toString() 
                  );
              } else if (snapshot.hasError) {
                return Text("${snapshot.error}");
              }
              return CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }
}

完成形 main.dart

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  MyApp({Key key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Future<ApiResults> res;
  @override
  void initState() {
    super.initState();
    res = fetchApiResults();
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'APIをPOSTで呼び出しJSONパラメータを渡す',
      theme: ThemeData(
        primarySwatch: Colors.yellow,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Api JSON Post Sample'),
        ),
        body: Center(
          child: FutureBuilder<ApiResults>(
            future: res,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(
                  snapshot.data.message.toString() 
                  );
              } else if (snapshot.hasError) {
                return Text("${snapshot.error}");
              }
              return CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }
}

class ApiResults {
  final String message;
  ApiResults({
    this.message,
  });
  factory ApiResults.fromJson(Map<String, dynamic> json) {
    return ApiResults(
      message: json['message'],
    );
  }
}

Future<ApiResults> fetchApiResults() async {
  var url = "http://172.16.0.223/creator/api/flutter_post_test";
  var request = new SampleRequest(id: 1234, name: '大和賢一郎');
  final response = await http.post(url,
      body: json.encode(request.toJson()),
      headers: {"Content-Type": "application/json"});
  if (response.statusCode == 200) {
    return ApiResults.fromJson(json.decode(response.body));
  } else {
    throw Exception('Failed');
  }
}

class SampleRequest {
  final int id;
  final String name;
  SampleRequest({
    this.id,
    this.name,
  });
  Map<String, dynamic> toJson() => {
    'id': id,
    'name': name,
  };
}

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
22
Help us understand the problem. What are the problem?