今天要介紹的是如何串接api,這邊介紹的套件是使用retrofit
串接API
下載套件
在檔案pubspec.yaml加入下放語法,最新版本可至retrofit確認
dependencies:
retrofit: ^3.0.1+1
json_annotation: ^4.6.0
dio: ^4.0.6
flutter_bloc: ^8.1.1
dev_dependencies:
retrofit_generator: any
build_runner: ^2.2.1
flutter_test:
sdk: flutter
json_serializable: ^6.4.0
載入好之後建立api.dart,api是使用public-apis
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://meowfacts.herokuapp.com")
abstract class RestClient {
factory RestClient(Dio dio, {String baseUrl}) = _RestClient;
@GET("/")
Future<ApiDataResponse> getApiData();
}
建立一個api_data_response.dart
import 'package:json_annotation/json_annotation.dart';
part 'api_data_response.g.dart';
@JsonSerializable()
class ApiDataResponse {
List<String> data;
ApiDataResponse({
required this.data,
});
factory ApiDataResponse.fromJson(Map<String, dynamic> json) => _$ApiDataResponseFromJson(json);
}
在定義好的API抽象類別後, 需要透過Terminal下指令,進行Code Generation, 以便自動產生對抽象類別實作的具象子類別:
flutter pub run build_runner build --delete-conflicting-outputs
執行好後,會發現產出了兩個檔案,api.g.dart以及api_data_response.g.dart
建立一個app_repository.dart
import 'package:dio/dio.dart';
import 'package:flutter_api_demo/api_data_response.dart';
import 'api.dart';
class AppRepository {
final RestClient _client = RestClient(Dio());
Future<ApiDataResponse> getApiData() async {
return _client.getApiData();
}
}
在main.dart放入MultiRepositoryProvider
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MultiRepositoryProvider(
providers: [
RepositoryProvider<AppRepository>(create: (_) => AppRepository()),
],
child: MaterialApp(
title: 'Flutter API Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
在Function中拿到api資料
var getApiData = await RepositoryProvider.of<AppRepository>(context)
.getApiData();
在Widget build(BuildContext context)
內,透過FutureBuilder拿到api的資料
FutureBuilder<GetApiDataResponse>(
future: RepositoryProvider.of<AppRepository>(context)
.getApiData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Text(snapshot.data!.data.first);
}
return Container();
},
)
若想要拿到兩個以上的api資料可以這樣寫
FutureBuilder<dynamic>(
future: Future.wait([
RepositoryProvider.of<AppRepository>(context).getApiData(),
RepositoryProvider.of<AppRepository>(context).getApiData2(),
]),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
var getApiData = snapshot.data[0]!;
var getApiData2 = snapshot.data[1]!;
return Text(getApiData.data.first+getApiData2.data.first);
}
return Container();
},
)
範例完成圖