3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Flutter】Retrofitを使ってHTTPリクエスト(GET)

Posted at

使用パッケージ

Diojson_serializable を使ったHTTPリクエストコード部分を自動生成してくれるもの。

叩くAPIは openweathermap を使わせてもらう。

使い方

pubspec.yaml にパッケージを追加

dependencies:
  json_annotation: ^4.8.1
  dio: ^5.1.2
  retrofit: ^4.0.1

dev_dependencies:
  build_runner: ^2.4.4
  json_serializable: ^6.7.0
  retrofit_generator: ^7.0.1

HTTPリクエスト用の抽象クラスを用意

import 'package:dio/dio.dart';
import 'package:flutter_retrofit/utils/city_weather.dart';
import 'package:retrofit/retrofit.dart';

part 'rest_client.g.dart';

@RestApi(baseUrl: 'https://api.openweathermap.org/data/2.5')
abstract class RestClient {
  factory RestClient(Dio dio, {String baseUrl}) = _RestClient;

  @GET('/weather')
  Future<City> getCityWeather(
    @Query("lat") String lat,
    @Query("lon") String lon,
    @Query("appid") String appid,
    @Query("units") String units,
    @Query("lang") String lang
  );
}

見たままではあるが、
@RestApi() でベースとなるURLを定義して、
@GET() で各APIの定義を行っていく。
@Query() でクエリパラメータを記述することも可能。

:warning: 生成後のファイルを参照してる部分もあるのでこの時点でエラーが出てるのは気にせず次に進む

コード生成

flutter pub run build_runner build

これを叩くことにより

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'rest_client.dart';

// **************************************************************************
// RetrofitGenerator
// **************************************************************************

// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers

class _RestClient implements RestClient {
  _RestClient(
    this._dio, {
    this.baseUrl,
  }) {
    baseUrl ??= 'https://api.openweathermap.org/data/2.5';
  }

  final Dio _dio;

  String? baseUrl;

  @override
  Future<City> getCityWeather(
    String lat,
    String lon,
    String appid,
    String units,
    String lang,
  ) async {
    const _extra = <String, dynamic>{};
    final queryParameters = <String, dynamic>{
      r'lat': lat,
      r'lon': lon,
      r'appid': appid,
      r'units': units,
      r'lang': lang,
    };
    final _headers = <String, dynamic>{};
    final Map<String, dynamic>? _data = null;
    final _result =
        await _dio.fetch<Map<String, dynamic>>(_setStreamType<City>(Options(
      method: 'GET',
      headers: _headers,
      extra: _extra,
    )
            .compose(
              _dio.options,
              '/weather',
              queryParameters: queryParameters,
              data: _data,
            )
            .copyWith(baseUrl: baseUrl ?? _dio.options.baseUrl)));
    final value = City.fromJson(_result.data!);
    return value;
  }

  RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
    if (T != dynamic &&
        !(requestOptions.responseType == ResponseType.bytes ||
            requestOptions.responseType == ResponseType.stream)) {
      if (T == String) {
        requestOptions.responseType = ResponseType.plain;
      } else {
        requestOptions.responseType = ResponseType.json;
      }
    }
    return requestOptions;
  }
}

のようなメソッドが自動生成される。
(端折ってしまったが、getCityWeather()内の final value = City.fromJson(_result.data!); で、 fromJson()メソッドを使用してレスポンスをクラス形式に変換している。ここの変換にjson_serializableで用意したコードが必要となる。(json_serializableで用意するクラスとしては、特別なものではなく、Retrofitを使用しない場合(Dioをそのまま使用する場合)と同等のもので問題ない))

これを使用して下記のようなコードを書くと結果が取得できる。

    // 東京タワーの緯度経度
    final lat = '35.6579781';
    final lon = '139.7433048';
    final appid = 'xxxxxxxxxx';
    final units = 'metric';
    final lang = 'ja';

    final dio = Dio();
    final client = RestClient(dio);

    final City city = await client.getCityWeather(lat, lon, appid, units, lang);

    // とりあえず場所と天気だけ表示
    print('CityWeathre: ${city.id}, ${city.name}, ${city.weather?[0].description}');

使ってみての感想

HTTPリクエスト部分と結果のマッピング部分を、
定義クラスだけ用意すれば自動生成してくれるのは便利。

だが、HTTPアクセスからマッピングまでが
final City city = await client.getCityWeather(lat, lon, appid, units, lang);
に隠蔽されているので、
定義するときに一部の記述を間違えたなどでうまく動かないときに、
どこが悪いのかを探すのがちょっと大変。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?