[Flutter] http통신하기

박망키·2022년 4월 6일
1

Flutter 야금야금 먹기

목록 보기
32/97
post-custom-banner

1.pubspec.yaml에 http 패키지 추가하기

dependencies:
http: <latest_version>

2. 네트워크 요청하기


dart:convert 패키지:응답 내용을 JSON Map으로 변환

빈칸엔 받아오려는 곳의 주소

3. 응답 정보를 커스텀 Dart 객체로 변환하기

3-1. 클래스를 생성하기

  • 네트워크 요청으로부터 받은 데이터를 지니고 있을 클래스를 생성한다(나의경우 Info)
  • JSON으로부터 Post를 생성하는 factory 생성자를 포함

3-2. http.Response를 Info로 변환하기

  • fetchPost() 함수가 Future를 반환하도록 수정하는 과정
  • 서버가 상태 코드 200과 함께 “OK” 응답을 반환하면, factory 메서드 fromJson()를 사용하여 JSON Map을 Post로 변환


4. 데이터 가져오기

  • fetch 메서드를 initState() 혹은 didChangeDependencies() 메서드 안에서 호출
    initState() 메서드는 딱 1번만 실행되고 절대 다시는 실행되지 않는다.
    InheritedWidget의 변경에 대한 응답으로 API를 다시 로드하고 싶다면 didChangeDependencies() 메서드 안에 호출을 넣는다.

    5. 데이터 보여주기

  • 데이터를 화면에 보여주기 위한 목적으로, FutureBuilder 위젯을 사용할 수 있다. FutureBuilder 위젯은 Flutter에 기본적으로 제공되는 위젯으로 비동기 데이터 처리를 쉽게 해준다.

    5-1. 원하는 Future를 넣는다. 여기서는 fetchInfo() 함수에서 반환된 future를 넣는다.

    5-2. Future의 상태(로딩, 성공 혹은 에러)에 따라 Flutter에게 무엇을 랜더링해야 할지 알려줄 builder 함수를 넣는다.

    fetchPost()를 initState()에서 호출하는 이유?
    Flutter는 무언가 변경될 때마다 build() 메서드를 호출하는데, 이 호출은 놀랄 만큼 자주 일어난다. 만약 네트워크 요청 코드를 build() 메서드에 그대로 남겨둔다면, 불필요한 API 요청이 아주 많이 발생하고 앱이 느려질 수 있다.

전체코드

<script>
 
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';

Future<Info> fetchInfo() async {
var url = 'https://api.mockaroo.com/api/5ee43e50?count=1&key=6213f2b0';
final response = await http.get(Uri.parse(url));

if (response.statusCode == 200) {
  //만약 서버가 ok응답을 반환하면, json을 파싱합니다
  print('응답했다');
  print(json.decode(response.body));
  return Info.fromJson(json.decode(response.body));
} else {
  //만약 응답이 ok가 아니면 에러를 던집니다.
  throw Exception('계좌정보를 불러오는데 실패했습니다');
}
}

class Info {
final int id;
final String userName;
final int account;
final int balance;

Info(
    {required this.id,
    required this.userName,
    required this.account,
    required this.balance});

factory Info.fromJson(Map<String, dynamic> json) {
  return Info(
    id: json["id"],
    userName: json["userName"],
    account: json["account"],
    balance: json["balance"],
  );
}

}

class InfoPage extends StatefulWidget {
const InfoPage({Key? key}) : super(key: key);

@override
State<InfoPage> createState() => _InfoPageState();
}

class _InfoPageState extends State<InfoPage> {
Future<Info>? info;

@override
void initState() {
  super.initState();
  info = fetchInfo();
}

@override
Widget build(BuildContext context) {
  return Scaffold(
      appBar: AppBar(
        title: Text('info', style: TextStyle(color: Colors.white)),
        centerTitle: true,
      ),
      body: Center(
        child: FutureBuilder<Info>(
          //통신데이터 가져오기
          future: info,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return buildColumn(snapshot);
            } else if (snapshot.hasError) {
              return Text("${snapshot.error}에러!!");
            }
            return CircularProgressIndicator();
          },
        ),
      ));
}

Widget buildColumn(snapshot) {
  return Column(
    mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [
      Text('고객번호:' + snapshot.data!.id.toString(),
          style: TextStyle(fontSize: 20)),
      Text('고객명:' + snapshot.data!.userName.toString(),
          style: TextStyle(fontSize: 20)),
      Text('계좌 아이디:' + snapshot.data!.account.toString(),
          style: TextStyle(fontSize: 20)),
      Text('잔액:' + snapshot.data!.balance.toString() + '원',
          style: TextStyle(fontSize: 20)),
    ],
  );
}
}

</script>

결과화면


짜잔 -!🎈

profile
무럭무럭 자라는 망키
post-custom-banner

0개의 댓글