본문 바로가기

Flutter/Skills

Dio + Retrofit + JsonSerializable 통한 서버 통신

Http 통신 테스트를 위한 무료 api 제공 사이트

https://reqres.in

 

Reqres - A hosted REST-API ready to respond to your AJAX requests

Native JavaScript If you've already got your own application entities, ie. "products", you can send them in the endpoint URL, like so: var xhr = new XMLHttpRequest(); xhr.open("GET", "https://reqres.in/api/products/3", true); xhr.onload = function(){ conso

reqres.in

 

요청 API : https://reqres.in/api/users/2

요청 API Json

{
    "data": {
        "id": 2,
        "email": "janet.weaver@reqres.in",
        "first_name": "Janet",
        "last_name": "Weaver",
        "avatar": "https://reqres.in/img/faces/2-image.jpg"
    },
    "support": {
        "url": "https://reqres.in/#support-heading",
        "text": "To keep ReqRes free, contributions towards server costs are appreciated!"
    }
}

 

코드 작성 순서

data.dart

import 'package:json_annotation/json_annotation.dart';

part 'data.g.dart';

@JsonSerializable()
class User {
  Data data;

  User({
    required this.data,
  });

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

@JsonSerializable()
class Data {
  Data({
    required this.id,
    required this.email,
    required this.firstName,
    required this.lastName,
    required this.avatar,
  });

  int id;
  String email;
  @JsonKey(name: 'first_name')
  String firstName;
  @JsonKey(name: 'last_name')
  String lastName;
  String avatar;

  factory Data.fromJson(Map<String, dynamic> json) => _$DataFromJson(json);
  Map<String, dynamic> toJson() => _$DataToJson(this);
}

 

 

rest_client.dart

import 'package:dio/dio.dart';
import 'package:retrofit/retrofit.dart';

import 'data.dart';

part 'rest_client.g.dart';

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

  @GET('/users/{id}')
  Future<User> getUser({@Path() required int id});
}

위의 2개의 파일에서

part 'data.g.dart''
part 'rest_client.g.dart'

위의 두개의 부분은 없는 파일로 인식하고 빨간줄이 뜬다.

당연하다.

 

터미널을 키고 에서 해당 프로젝의 root 경로에서 아래 명령문을 실행 시킨다.

flutter pub run build_runner build

## 추가설명
flutter pub run build_runner build : 1회 빌드
flutter pub run build_runner watch : 파일 변경이 발생하면 빌드

(data.g.dart , rest_client.g.dart 파일이 자동적으로 생성된다)

 

 

 

retrofit_dio_json.dart

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'custom_log_interceptor.dart';
import 'data.dart';
import 'rest_client.dart';

class RetrofitDioJson extends StatelessWidget {
  RetrofitDioJson({Key? key}) : super(key: key);

  final dio = Dio()
    ..interceptors.add(
      CustomLogInterceptor(),
    );

  @override
  Widget build(BuildContext context) {
    final _client = RestClient(dio);

    return Scaffold(
      appBar: AppBar(
        title: Text('Dio'),
      ),
      body: Center(
        child: FutureBuilder<User?>(
          future: _client.getUser(id: 1),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              User? userInfo = snapshot.data;
              if (userInfo != null) {
                Data userData = userInfo.data;
                return Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Image.network(userData.avatar),
                    SizedBox(height: 16.0),
                    Text(
                      '${userInfo.data.firstName} ${userInfo.data.lastName}',
                      style: TextStyle(fontSize: 24.0),
                    ),
                    Text(
                      userData.email,
                      style: TextStyle(fontSize: 24.0),
                    ),
                  ],
                );
              }
            }
            return CircularProgressIndicator();
          },
        ),
      ),
    );
  }
}

 

 

 

custom_log_interceptor.dart

import 'package:dio/dio.dart';

class CustomLogInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    print('REQUEST[${options.method}] => PATH: ${options.path}');
    super.onRequest(options, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    print(
      'RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}',
    );
    super.onResponse(response, handler);
  }

  @override
  void onError(DioError err, ErrorInterceptorHandler handler) {
    print(
      'ERROR[${err.response?.statusCode}] => PATH: ${err.requestOptions.path}',
    );
    super.onError(err, handler);
  }
}

 

 

 

Github 코드

https://github.com/hunderboy/FlutterFunctionModules/tree/master/lib/retrofit_dio_json

 

GitHub - hunderboy/FlutterFunctionModules: 플러터의 각 기능을 모듈화한 Repository.

플러터의 각 기능을 모듈화한 Repository. Contribute to hunderboy/FlutterFunctionModules development by creating an account on GitHub.

github.com

 

 

 

'Flutter > Skills' 카테고리의 다른 글

제네릭 <T> 를 사용할때, 착각하기 쉬운 경우  (0) 2024.11.26
Pagination  (0) 2024.11.05
Unit Test  (0) 2022.12.01
gskinner  (0) 2022.11.22
Flutter Favorite program  (0) 2022.11.14