iT邦幫忙

2022 iThome 鐵人賽

DAY 5
0
Mobile Development

在 Flutter 開發旅程的手札系列 第 5

Flutter Package - 串接api(一)

  • 分享至 

  • xImage
  •  

今天要介紹的是如何串接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

https://ithelp.ithome.com.tw/upload/images/20220920/20152683ivBmI4nIWN.png


載入好之後建立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

https://ithelp.ithome.com.tw/upload/images/20220920/20152683EwNkTDP4JM.png


建立一個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();
  },
)
  

範例完成圖
https://ithelp.ithome.com.tw/upload/images/20220921/20152683tR8MXA88lX.png


上一篇
Flutter Package - 製作多國語系
下一篇
Flutter Package - 串接api(二)
系列文
在 Flutter 開發旅程的手札30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言