昨天介紹了一下GET
但是POST就麻煩得多,基本上有以下三種
另外在Flutter裡有三種常見的網路請求作法
今天就來測試一下3*3種情境該怎麼寫

網路開放資源,可隨意測試
application/json
http://httpbin.org/delay/1
application/x-www-form-urlencoded
https://reqres.in/api/login
multipart/form-data
https://postman-echo.com/post
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:dio/dio.dart';
import 'package:idlf/model/User.dart';
typedef UsersCallback = void Function(Users);
class APIManager {
  //以下POST HttpClient分隔線=================
  void loginHttpClientWWW(void Function() success, void Function() fail) async {
    var urlString = "https://reqres.in/api/login";
    HttpClient()
        .postUrl(Uri.parse(urlString))
        .then((HttpClientRequest request) {
      request.headers.contentType = ContentType("application", "x-www-form-urlencoded");
      request.write("{\"email\":\"eve.holt@reqres.in\",\"password\":\"cityslicka\"}");
//      request.write("email=eve.holt@reqres.in");
//      request.write("password=cityslicka");
      return request.close();
    }).then((HttpClientResponse response) {
      if (response.statusCode == 200) {
        response.transform(utf8.decoder).join().then((String string) {
          print("HttpClientWWW Success:$string");
          success();
        });
      } else {
        print("HttpClientWWW Fail:${response.statusCode}");
        fail();
      }
    });
  }
  void loginHttpClientJson(void Function() success, void Function() fail) async {
    var urlString = "http://httpbin.org/delay/1";
    HttpClient()
        .postUrl(Uri.parse(urlString))
        .then((HttpClientRequest request) {
      request.headers.contentType = ContentType("application", "json");
      Map<String,String> p = {"UserName":"eve.holt@reqres.in", "Password":"cityslicka"};
      request.add(utf8.encode(json.encode(p)));
      return request.close();
    }).then((HttpClientResponse response) {
      if (response.statusCode == 200) {
        response.transform(utf8.decoder).join().then((String string) {
          print("HttpClientJson Success:$string");
          success();
        });
      } else {
        print("HttpClientJson Fail:${response.statusCode}");
        fail();
      }
    });
  }
  void loginHttpClientForm(void Function() success, void Function() fail) async {
  }
  //以下POST http分隔線=================
  void loginHttpWWW(void Function() success, void Function() fail) async {
    var urlString = "https://reqres.in/api/login";
    Map<String, String> headersMap = new Map();
    headersMap["content-type"] = "application/x-www-form-urlencoded";
    Map<String, String> bodyParams = new Map();
    bodyParams["email"] = "eve.holt@reqres.in";
    bodyParams["password"] = "cityslicka";
    http.Client()
        .post(urlString, headers: headersMap, body: bodyParams, encoding: Utf8Codec())
        .then((http.Response response) {
      if (response.statusCode == 200) {
        print("httpWWW Success:${response.body}");
        success();
      } else {
        print("httpWWW Fail:${response.statusCode}");
        fail();
      }
    }).catchError((error) {
      print("httpWWW Fail:${error.toString()}");
      fail();
    });
  }
  void loginHttpJson(void Function() success, void Function() fail) async {
    var urlString = "http://httpbin.org/delay/1";
    Map<String, String> headersMap = new Map();
    headersMap["content-type"] = ContentType.json.toString();
    Map<String, String> bodyParams = new Map();
    bodyParams["email"] = "eve.holt@reqres.in";
    bodyParams["password"] = "cityslicka";
    http.Client()
        .post(urlString, headers: headersMap, body: jsonEncode(bodyParams), encoding: Utf8Codec())
        .then((http.Response response) {
      if (response.statusCode == 200) {
        print("httpJson Success:${response.body}");
        success();
      } else {
        print("httpJson Fail:${response.statusCode}");
        fail();
      }
    }).catchError((error) {
      print("httpJson Fail:${error.toString()}");
      fail();
    });
  }
  void loginHttpForm(void Function() success, void Function() fail) async {
    var urlString = "https://postman-echo.com/post";
    var client = new http.MultipartRequest("post", Uri.parse(urlString));
    client.fields["email"] = "eve.holt@reqres.in";
    client.fields["password"] = "cityslicka";
    client.send().then((http.StreamedResponse response) {
      if (response.statusCode == 200) {
        response.stream.transform(utf8.decoder).join().then((String string) {
          print("httpForm Success:$string");
          success();
        });
      } else {
        print("httpForm Fail:${response.statusCode}");
        fail();
      }
    }).catchError((error) {
      print("httpForm Fail:${error.toString()}");
      fail();
    });
  }
  //以下POST Dio分隔線=================
  void loginDioWWW(void Function() success, void Function() fail) async {
    var urlString = "https://reqres.in/api/login";
    try {
      Response response = await Dio()
        .post(urlString,
          data: {"email":"eve.holt@reqres.in", "password":"cityslicka"},
          options: Options(contentType:Headers.formUrlEncodedContentType));
      print("DioWWW Success:${response.data}");
      success();
    } catch (error) {
      print("DioWWW Fail:${error.toString()}");
      fail();
    }
  }
  void loginDioJson(void Function() success, void Function() fail) async {
    var urlString = "http://httpbin.org/delay/1";
    try {
      Response response = await Dio()
          .post(urlString,
          data: {"email":"eve.holt@reqres.in", "password":"cityslicka"},
          options: Options(contentType:Headers.jsonContentType));
      print("DioJson Success:${response.data}");
      success();
    } catch (error) {
      print("DioJson Fail:${error.toString()}");
      fail();
    }
  }
  void loginDioForm(void Function() success, void Function() fail) async {
    var urlString = "https://postman-echo.com/post";
    try {
      Response response = await Dio()
          .post(urlString,
          data: FormData.fromMap({"email":"eve.holt@reqres.in", "password":"cityslicka"}));
      print("DioForm Success:${response.data}");
      success();
    } catch (error) {
      print("DioForm Fail:${error.toString()}");
      fail();
    }
  }
}
class LessonPageApiPost extends StatefulWidget {
  @override
  _LessonPageApiPostState createState() => _LessonPageApiPostState();
}
class _LessonPageApiPostState extends State<LessonPageApiPost> {
  final long = 66.0;
  final List<bool> formDataResults = [null, null, null];
  final List<bool> jsonResults = [null, null, null];
  final List<bool> wwwResults = [null, null, null];
  
  Widget _createContainer(String text) {
    return Container(
      height: long,
      alignment: Alignment.center,
      child: Text(text),
    );
  }
  Widget _createResultWidget(bool result) {
    if (result == true) {
      return _createContainer("⭕️");
    } else if (result == false) {
      return _createContainer("❌");
    } else {
      return Container(
          height: long,
          child: CupertinoActivityIndicator()
      );
    }
  }
  Widget _createTable() {
    return Table(
      columnWidths: {
        1: FixedColumnWidth(long),
        2: FixedColumnWidth(long),
        3: FixedColumnWidth(long),
      },
      children: [
        TableRow(
            children: [
              _createContainer(""),
              _createContainer("HttpClient"),
              _createContainer("http"),
              _createContainer("Dio"),
            ]
        ),
        TableRow(
            children: [
              _createContainer("json"),
              _createResultWidget(jsonResults[0]),
              _createResultWidget(jsonResults[1]),
              _createResultWidget(jsonResults[2]),
            ]
        ),
        TableRow(
            children: [
              _createContainer("x-www-form-urlencoded"),
              _createResultWidget(wwwResults[0]),
              _createResultWidget(wwwResults[1]),
              _createResultWidget(wwwResults[2]),
            ]
        ),
        TableRow(
            children: [
              _createContainer("form-data"),
              _createResultWidget(formDataResults[0]),
              _createResultWidget(formDataResults[1]),
              _createResultWidget(formDataResults[2]),
            ]
        )
      ]
    );
  }
  @override
  void initState() {
    super.initState();
    //=============www
    APIManager().loginHttpClientWWW(() {
      setState(() { wwwResults[0] = true; });
    }, () {
      setState(() { wwwResults[0] = false; });
    });
    APIManager().loginHttpWWW(() {
      setState(() { wwwResults[1] = true; });
    }, () {
      setState(() { wwwResults[1] = false; });
    });
    APIManager().loginDioWWW(() {
      setState(() { wwwResults[2] = true; });
    }, () {
      setState(() { wwwResults[2] = false; });
    });
    //=============json
    APIManager().loginHttpClientJson(() {
      setState(() { jsonResults[0] = true; });
    }, () {
      setState(() { jsonResults[0] = false; });
    });
    APIManager().loginHttpJson(() {
      setState(() { jsonResults[1] = true; });
    }, () {
      setState(() { jsonResults[1] = false; });
    });
    APIManager().loginDioJson(() {
      setState(() { jsonResults[2] = true; });
    }, () {
      setState(() { jsonResults[2] = false; });
    });
    //=============Form
    APIManager().loginHttpClientForm(() {
      setState(() { formDataResults[0] = true; });
    }, () {
      setState(() { formDataResults[0] = false; });
    });
    APIManager().loginHttpForm(() {
      setState(() { formDataResults[1] = true; });
    }, () {
      setState(() { formDataResults[1] = false; });
    });
    APIManager().loginDioForm(() {
      setState(() { formDataResults[2] = true; });
    }, () {
      setState(() { formDataResults[2] = false; });
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("第十六堂課"),
      ),
      body: Padding(
        padding: EdgeInsets.only(right: 8),
        child: _createTable()
      )
    );
  }
}
本集內容Android版請見:iOS Developer Learning Android. Lesson 18
下集預告:生命週期
最後提供一下github.com/mark33699/IDLF