iT邦幫忙

2021 iThome 鐵人賽

DAY 7
1
Mobile Development

Flutter - 複製貼上到開發套件之旅系列 第 7

【第七天 - Flutter Api、Json 物件教學】

前言

今日的程式碼 => GITHUB

https://ithelp.ithome.com.tw/upload/images/20210904/20134548DJfhiJtaOV.png

這邊我會用到 json_serializable 的套件和 HttpEquatable 的套件。這兩個是超級重要的套件,喜歡的話可以在 pub.dev 加到我的最愛呦~

這編我要請求 https://jsonplaceholder.typicode.com/posts/1 這個網址的資料,並顯示在手機上面

Yaml 設定

  • Json 設定,這邊因為現在套件最新版本,是支援 Flutter 的 dev branch。而不是支援 flutter 的 meta 版本,所以這邊我是有把版本降下了一些

可以參考 教學範例

dependencies:
  json_annotation: ^4.0.0
dev_dependencies:
  build_runner: ^2.0.0
  json_serializable: ^4.0.0
  • API 設定
dependencies:
 http: ^0.13.3
 equatable: ^2.0.3

物件教學

我們先來看 https://jsonplaceholder.typicode.com/posts/1 的 JSON 樣子是什麼。不清楚什麼是 JSON 的話可以看這裡 => W3School

{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}

1. 創建一個 .dart 的檔案名稱為 post_model.dart

post_model.dart

Equatable 是用來讓物件可以等於物件的。詳細可以看 Equatable 套件說明

import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';

part 'post_model.g.dart';
// 變成 黨名.g.dart
@JsonSerializable()
class PostModel extends Equatable{
  final int userId;// json 欄位名稱
  final int id;// json 欄位名稱
  final String title;// json 欄位名稱
  final String body;// json 欄位名稱
  PostModel({required this.userId, required this.id, required this.title, required this.body});// required 裡面也要改成
  factory PostModel.fromJson(Map<String, dynamic> json) => _$PostModelFromJson(json);
  // 這裡的 PostModel.fromJson 的 PostModel 也要改動,後面的 _$PostModelFromJson 的 PostModelFromJson 也要改動
  // 變成 XXX.fromJson _$XXXFromJson
  Map<String, dynamic> toJson() => _$PostModelToJson(this);
  // 這裡的 _$PostModelToJson(this) 的 PostModel 也要改動,變成  _$XXXToJson(this)
  @override
  String toString() => "$userId $id $title $body";

  @override
  List<Object?> get props => [userId, id, title, body];
}

自動產生 .g.dart 檔案

這邊超神奇的,我們去終端機吧,下完指令,會產生一個 post_model.g.dart 的檔案

flutter pub run build_runner build

Http Get 怎麼使用

這邊官方文件寫得蠻清楚的 => HTTP
以下是範例的 HTTP 使用部分,裡面的參數 apidata 是一個我在 function 外面宣告的變數

  void fetchData() async {
    // 請求時間錊多幾秒
    const timeout = Duration(seconds: 10);
    // URI 需要傳入 String authority, String unencodedPath, [Map<String, dynamic>? queryParameters
    var url = Uri.https('jsonplaceholder.typicode.com', '/posts/1',);
    // Await the http get response, then decode the json-formatted response.
    var response = await http.get(url).timeout(timeout);
    // 如果是 response.statusCode 是 200 的話,我們再去解析 Json
    if (response.statusCode == 200) {
      setState(() {
        apidata = PostModel.fromJson(json.decode(response.body));
      });
      // 如果需要 是 List<PostModel> 的話可以使用下面的方式。
      // List<PostModel>.from(json.decode(response.body).map((c) => PostModel.fromJson(c)).toList());
    } else {
      throw Exception();
    }
  }

MyHomePageState

class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> {
/// 初始化的資料,之後請求到資料後,存在這裡。
PostModel? apidata;

@override
void initState() {
  super.initState();
  // 請求資料
  fetchData();
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('API Sample'),
    ),
    body: Center(
      child: Text(
        apidata == null ? "" : apidata.toString(),
        textAlign: TextAlign.center,
        style: TextStyle(fontSize: 20),
      ),
    ),
  );
}

void fetchData() async {
  // 請求時間最多幾秒
  const timeout = Duration(seconds: 10);
  // URI 可以傳入 String authority, String unencodedPath, [Map<String, dynamic>? queryParameters
  var url = Uri.https(
    'jsonplaceholder.typicode.com',
    '/posts/1',
  );
  // Await the http get response, then decode the json-formatted response.
  var response = await http.get(url).timeout(timeout);
  // 如果是 response.statusCode 是 200 的話,我們再去解析 Json
  if (response.statusCode == 200) {
    setState(() {
      apidata = PostModel.fromJson(json.decode(response.body));
    });
    // 如果需要 是 List<PostModel> 的話可以使用下面的方式。
    // List<PostModel>.from(json.decode(response.body).map((c) => PostModel.fromJson(c)).toList());
  } else {
    throw Exception();
  }
}
}

補充: HTTP Post 使用

這邊是參考 HTTP 套件包,裡面的 Sample Code

var client = http.Client();
try {
var uriResponse = await client.post(Uri.parse('https://example.com/whatsit/create'),
    body: {'name': 'doodle', 'color': 'blue'});
print(await client.get(uriResponse.bodyFields['uri']));
} finally {
client.close();
}

上一篇
【第六天 - Flutter 多國語系】
下一篇
【第八天 - Flutter Provider 架構教學】
系列文
Flutter - 複製貼上到開發套件之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

我要留言

立即登入留言