[Flutter-REST API] http 통신

김선욱·2024년 1월 23일

Flutter

목록 보기
2/9
post-thumbnail
  • 해당 포스팅을 읽어보기 전에 REST API가 궁금하다면 해당 링크 [Network] REST & REST API & RESTful API를 통해서 REST API에 대하여 학습해보기를 권장한다.
  • 앱을 개발 할 때에 API 통신은 굉장히 자주 사용된다. 해당 포스팅은 Flutter에서 사용되는 API 통신 라이브러리를 사용해 볼 것이다.
  • 무료 API 사이트 : Lorem Picsum

 

http | Dart Package

  • 해당 라이브러리를 플러터의 pubspec.yaml에 추가하여 준다.
    flutter pub add http // 터미널 명령어

 

picsum_model.dart

class PicsumModel {
  final String id;
  final String author;
  final int width;
  final int height;
  final String url;
  final String downloadUrl;

  PicsumModel({
    required this.id,
    required this.author,
    required this.width,
    required this.height,
    required this.url,
    required this.downloadUrl,
  });
}
  • 무료 API 사이트 Lorem Picsum의 데이터 모델을 만들어 준다. 해당 객체 모델은 id, author, width, height, url, downloadUrl을 필드 값으로 가지고 있다.

 

class PicsumModel {
	.
	.
	.

	// 방법1
	PicsumModel.fromJson(Map<String, dynamic> json)
      : id = json["id"],
        author = json["author"],
        width = json["width"],
        height = json["height"],
        url = json["url"],
        downloadUrl = json["download_url"];

	// 방법2
	factory PicsumModel.fromJson(Map<String, dynamic> json) {
    return PicsumModel(
      id: json["id"],
      author: json["author"],
      width: json["width"],
      height: json["height"],
      url: json["url"],
      downloadUrl: json["download_url"],
    );
  }

	.
	.
	.
}
  • 해당 API 데이터를 가져올 때, json 형태의 구조를 앱에서 사용할 객체로 변환해야 한다.

 

picsum_repository.dart

import 'dart:convert';

import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';

import 'picsum_model.dart';

class PicsumRepository {
  PicsumRepository._privateConstructor();
  static final PicsumRepository _instance =
      PicsumRepository._privateConstructor();
  static PicsumRepository get instance => _instance;

  Future<List<PicsumModel>> fetchData() async {
    try {
      int pageNumber = 1;
      http.Response response = await http.get(
        Uri.parse(
          "https://picsum.photos/v2/list?page=$pageNumber&limit=10",
        ),
      );
      if (response.statusCode == 200) {
        List<dynamic> data = json.decode(response.body);
        List<PicsumModel> result = data.map((element) {
          return PicsumModel.fromJson(element);
        }).toList();
        return result;
      } else {
        return [];
      }
    } catch (error) {
      debugPrint('[picsum_repository / _fetchData] $error');
      return [];
    }
  }
}
  • http와 json을 이용하기 위해서 'dart:convert''package:http/http.dart' as http를 import 해주었다.
  • 해당 함수는 특정 페이지의 데이터를 가져오도록 구현하였고, 필요에 따라 해당 pageNumber 변수의 값에 변화를 주여 다른 페이지의 데이터를 가지고 올 수 있다.
  • API 통신은 비동기 통신이기 때문에 async-await를 사용하여 비동기 처리를 해주어야 한다.
  • 해당 예제에서는 http.get으로 GET 방식의 REST API를 호출하였다.
  • Uri.parse를 사용하여 API호출 주소를 URI 방식으로 변경하였고, 이에 대한 응답을 http.Response의 타입으로 선언된 response 변수에 담아주었다.
  • 해당 response의 상태 코드를 확인하여 정상(200)이면 데이터를 가지고 온다.
  • 응답 받은 response의 body에 데이터가 있는데, 이는 json 형태이기에 앞서 PicsumModel에 정의해준 fromJson을 사용하여 PicsumModel로 데이터를 변환해준다.

 

picsum_view.dart

import 'package:flutter/material.dart';

import 'picsum_model.dart';
import 'picsum_repository.dart';

class PicsumView extends StatefulWidget {
  const PicsumView({super.key});

  
  State<PicsumView> createState() => _PicsumViewState();
}

class _PicsumViewState extends State<PicsumView> {
  List<PicsumModel> picsumModelList = [];
  bool isLoading = false;

  
  void initState() {
    initializeData();
    super.initState();
  }

  Future<void> initializeData() async {
    setState(() {
      isLoading = true;
    });
    picsumModelList = await PicsumRepository.instance.fetchData();
    setState(() {
      isLoading = false;
    });
  }

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: isLoading
          ? const Scaffold(
              body: Center(
                child: CircularProgressIndicator(),
              ),
            )
          : Scaffold(
              body: ListView.builder(
                itemCount: picsumModelList.length,
                itemBuilder: (BuildContext context, index) {
                  return picsumCardWidget(context, index);
                },
              ),
            ),
    );
  }

  Widget picsumCardWidget(context, int index) {
    return Container(
      height: MediaQuery.of(context).size.height * 0.15,
      width: MediaQuery.of(context).size.width,
      margin: EdgeInsets.symmetric(
        vertical: MediaQuery.of(context).size.height * 0.01,
        horizontal: MediaQuery.of(context).size.width * 0.03,
      ),
      decoration: BoxDecoration(
        color: Colors.grey[200],
        borderRadius: BorderRadius.circular(16),
      ),
      child: Row(
        children: [
          SizedBox(width: MediaQuery.of(context).size.width * 0.02),
          ClipRRect(
            borderRadius: BorderRadius.circular(16),
            child: Image.network(
              picsumModelList[index].downloadUrl,
              height: MediaQuery.of(context).size.height * 0.13,
              width: MediaQuery.of(context).size.height * 0.13,
              fit: BoxFit.cover,
            ),
          ),
          SizedBox(width: MediaQuery.of(context).size.width * 0.04),
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                'ID : ${picsumModelList[index].id}',
                style: const TextStyle(fontWeight: FontWeight.bold),
              ),
              Text('Author : ${picsumModelList[index].author}'),
              Text('Height : ${picsumModelList[index].height}'),
              Text('Width : ${picsumModelList[index].width}'),
            ],
          ),
        ],
      ),
    );
  }
}
  • isLoading 변수는 데이터를 가지고 오는 동안에 로딩 화면을 띄어주기 위해 사용되었다.
  • picsumModelList 변수에 위에 PicsumRepository에서 정의한 fetchData를 사용하여 데이터를 가지고 왔다.
  • ListView.builder를 사용하여 picsumCardWidget의 형태로 화면을 나타냈다.

 

결과물

 


Ref.

profile
💻 Flutter Developer

0개의 댓글