點燈坊

失くすものさえない今が強くなるチャンスよ

http 呼叫 POST REST API

Sam Xiao's Avatar 2024-11-15

http 可呼叫 POST REST API 以 Future 形式回傳。

Version

Flutter 3.24

http

$ flutter pub add http
  • 安裝 http package

Flutter

post01

  • Android 與 iOS 都成功以 POST 呼叫 REST API

POST

import 'dart:convert';

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

class Home extends StatefulWidget {
  const Home({super.key});

  
  State<Home> createState() => _Home();
}

class _Home extends State<Home> {
  var _id = '';

  Future<String> _addPost() async {
    final url = Uri.parse(
      'https://jsonplaceholder.typicode.com/posts',
    );

    final headers = {"Content-Type": "application/json"};

    final body = jsonEncode({
      "title": "foo",
      "body": "bar",
      "userId": 1,
    });

    try {
      final response = await http.post(
        url,
        headers: headers,
        body: body,
      );

      if (response.statusCode == 201) {
        final data = jsonDecode(response.body);
        return data["id"].toString();
      } else {
        if (kDebugMode) {
          print(response.statusCode);
        }
        return '';
      }
    } catch (e) {
      if (kDebugMode) {
        print(e);
      }
      return '';
    }
  }

  
  Widget build(BuildContext context) {
    var appBar = AppBar(
      title: const Text('http post'),
    );

    var floatingActionButton = FloatingActionButton(
        onPressed: () async {
          var id = await _addPost();
          setState(() => _id = id);
        },
        child: const Icon(Icons.add));

    var body = Center(
      child: Text(_id),
    );

    return Scaffold(
      appBar: appBar,
      floatingActionButton: floatingActionButton,
      body: body,
    );
  }
}

Line 17

Future<String> _addPost() async {
}
  • _addPost():呼叫 POST REST API 回傳 Future,實務上會抽到 Service 內
  • 因為回傳 Future,所以為 async function

Line 18

final url = Uri.parse(
  'https://jsonplaceholder.typicode.com/posts',
);
  • Uri.parse():將 url 轉成 Uri 物件

Line 22

final headers = {"Content-Type": "application/json"};
  • 當呼叫 POST REST API 時,必須指定 headers

Line 24

final body = jsonEncode({
  "title": "foo",
  "body": "bar",
  "userId": 1,
});
  • body:組合 body,最後必須使用 jsonEncode()Map 轉成 JSON String

Line 31

final response = await http.post(
  url,
  headers: headers,
  body: body,
);
  • http.post():呼叫 POST REST API,因為 http.post() 回傳 Future,所以要使用 await

Line 37

if (response.statusCode == 201) {
  final data = jsonDecode(response.body);
  return data["id"].toString();
}
  • 若回傳 statusCode 為 200,則從 response.body 取出資料
  • response.body 為 String,需使用 jsonDecoce() 將 String 轉成 Map

Line 41

if (kDebugMode) {
  print(response.statusCode);
}
return '';
  • kDebugMode:在 debug 模式印出 statusCode

Line 46

catch (e) {
  if (kDebugMode) {
    print(e);
  }
  return '';
}
  • kDebugMode:在 debug 模式印出錯誤訊息

Line 61

onPressed: () async {
  var id = await _addPost();
  setState(() => _id = id);
},
  • onPressed():當 FloatingActionButton 按下時呼叫 _addPost(),並將回傳值存進 _id state

Line 67

var body = Center(
  child: Text(_id),
);
  • _id state 改變時,會自動更新 Text

Conclusion

  • 呼叫 POST REST API 為非同步行為,所以 http.post() 會回傳 Future,因此須以 async function 處理
  • 當呼叫 POST REST API 時,並不會直接更新 UI,而是將值存進 state,由 Flutter 自動更新 UI

Reference

pub.dev, http