昨天已經有介紹如何串接API,以及教大家如何GET API資料,今天我們就來介紹POST
在api.dart檔案裡面多一個RestApi(因路徑與昨天使用的是不同的,因此需要再重新建立一個Client),api是使用Postman Echo
import 'package:json_annotation/json_annotation.dart';
import 'package:retrofit/retrofit.dart';
import 'package:dio_http/dio_http.dart';
part 'api.g.dart';
@RestApi(baseUrl: "https://postman-echo.com")
abstract class PostClient {
factory PostClient(Dio dio, {String baseUrl}) = _PostClient;
@POST("/post")
Future<PostDataResponse> postApiData(@Body() dynamic data);
}
建立一個post_data_response.dart
import 'package:json_annotation/json_annotation.dart';
part 'post_data_response.g.dart';
@JsonSerializable()
class PostDataResponse {
PostData data;
PostDataResponse({
required this.data,
});
factory PostDataResponse.fromJson(Map<String, dynamic> json) => _$PostDataResponseFromJson(json);
}
@JsonSerializable()
class PostData {
String content;
PostData({
required this.content,
});
factory PostData.fromJson(Map<String, dynamic> json) => _$PostDataFromJson(json);
}
在定義好的API抽象類別後, 需要透過Terminal下指令,進行Code Generation, 以便自動產生對抽象類別實作的具象子類別:
flutter pub run build_runner build --delete-conflicting-outputs
執行好後,會發現產出了一個新的檔案,post_data_response.g.dart,api.g.dart裡面的內容也會有調整
在app_repository.dart 的AppRepository class內加入PostClient
import 'package:dio/dio.dart';
import 'package:flutter_api_demo/post_data_response.dart';
import 'api.dart';
class AppRepository {
final PostClient _postClient = PostClient(Dio());
Future<PostDataResponse> postApiData(dynamic body) async {
return _postClient.postApiData(body);
}
}
透過Button傳送postApiData範例
ElevatedButton(
onPressed: () async {
final apiResponse = await RepositoryProvider.of<AppRepository>(context).postApiData({
"content": "Test Data",
});
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(apiResponse.data.content),
));
},
child: const Text("Post Button"),
)
範例完成圖
補充說明,dynamic的做法不是一個很嚴謹的做法,但可以幫助我們在初期比較好入手api。在開發上,我們會有一個Request的檔案,專門用來存POST的資料
建立一個post_data_request.dart檔案,輸入下方程式碼
import 'package:json_annotation/json_annotation.dart';
part 'post_data_request.g.dart';
@JsonSerializable()
class PostDataRequest {
String content;
PostDataRequest({
required this.content,
});
Map<String, dynamic> toJson() => _$PostDataRequestToJson(this);
}
在api.dart檔案將
@POST("/post")
Future<PostDataResponse> postApiData(@Body() dynamic data);
更改為
@POST("/post")
Future<PostDataResponse> postApiData(@Body() PostDataRequest data);
要記得import 'package:flutter_api_demo/post_data_request.dart';
再跑一次,讓檔案更新
flutter pub run build_runner build --delete-conflicting-outputs
在app_repository.dart將
final PostClient _postClient = PostClient(Dio());
Future<PostDataResponse> postApiData(dynamic body) async {
return _postClient.postApiData(body);
}
更改為
final PostClient _postClient = PostClient(Dio());
Future<PostDataResponse> postApiData(PostDataRequest body) async {
return _postClient.postApiData(body);
}
要記得import 'package:flutter_api_demo/post_data_request.dart';
透過Button傳送postApiData範例
ElevatedButton(
onPressed: () async {
final apiResponse = await RepositoryProvider.of<AppRepository>(context).postApiData(PostDataRequest(
content: "Test Data",
));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(apiResponse.data.content),
));
},
child: const Text("Post Button"),
)