【第七天 - 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();
}

<<:  关於抽象

>>:  [Day-21] R语言 - 分群应用(二) 离群值侦测 - 下 ( detect outlier by clustering in R.Studio )

Day6 - Hello World!!!

一切准备就绪 前置任务已经破玩了 今天要开始写我的第一个APP 大多数程序语言第一个写的程序几乎都是...

Day1 30天计画总览

今日要点 起源 介绍 起源 购入了奔跑吧linux套书,为了强迫自己每天推进一点进度,决定参与铁人赛...

python 中 pickle 读档问题的解决方法

前言 要读取 .pkl 档,结果遇到各种状况,在网路上查了许多资料後终於解决了! 在这边简单做个过程...

[day12]Heroku 基本使用

如果你有自己的固定IP,可以在本机进行部署,或着使用免费版本的Heroku Platform在云端建...

Node套件运用测试

因为我看到说node可以利用套件来使撰写程序较简单方便些,所以我这边就想用express套件来做个简...