본문 바로가기

그 땐 App했지/그 땐 Flutter했지

[TAVE/Study]Do it! Flutter 7장 네트워크를 이용해 통신하기①

728x90

211004 월

이번에는 내가 발표다! 예!

 

외부 패키지 이용하기


📌 HTTP: 네트워크와 연결하는 통신 규약
👉🏻 pub.dev 사이트에 들어가 원하는 기능 패키지를 찾아 pubspec.yaml 파일에 이름을 등록한다. (https://pub.dev/)
✍🏻 BSD: 자유롭게 만들고 배포할 수 있는 라이선스

 

카카오 API 이용하기

📌 API 키: 어플리케이션이 서버의 문을 여는 열쇠, 이 키로 데이터를 요청하고 분석한다.
👉🏻 로그인 > [내 애플리케이션] > [애플리케이션 추가하기] > 앱 이름에 "httpTest" 입력 > 사업자명에 각자 이름 입력

 

HTTP 통신 연습하기
dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 http: ^0.13.3

👉🏻 pubspec.yaml의 dependencies에 패키지 추가한다. 패키지 이름 + 콜론(:), 캐럿(^) + 버전

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

👉🏻 패키지를 불러온다.

class _HttpApp extends State<HttpApp> { String result = ''; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Http Example'), ), body: Container( child: Center( child: Text('$result'), ), ), floatingActionButton: FloatingActionButton( onPressed: () async { var url = 'http://www.google.com'; var response = await http.get(Uri.parse(url)); setState(() { result = response.body; }); }, child: Icon(Icons.file_download), ), ); } }

👉🏻 접속할 대상(구글 url)을 추가한다.
✍🏻 get: GET 방식으로 URL에 접속하는 코드
✍🏻 async, await: 비동기 처리방식, 정확한 데이터를 불러오고 처리해야해서 다 불러올 때까지 기다려준다.

 

책 정보 가져오기

📌 JSON: 데이터 통신할 때 이용, 파일 크기가 작고 태그를 이용해 값을 확인할 수 있다.

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

👉🏻 convert를 임포트 해야 JSON 사용 가능

 floatingActionButton: FloatingActionButton( onPressed: () { getJSONData(); }, child: Icon(Icons.file_download), ), (...생략...) Future<String> getJSONData() async { var url = 'https://dapi.kakao.com/v3/search/book?target=title&query=doit'; var response = await http.get(Uri.parse(url)), headers: {"Authorization": "KakaoAK 3f9ebc77f4d85936ab9aba99db774751" print(response.body); return "Successful"; }

👉🏻 헤더에 REST API키를 입력한다.
✍🏻 target 파라미터에 title 전달, query 파라미터에 검색어 doit 전달
✍🏻 도메인 ? 이후에 파라미터 전달해서 데이터를 요청하고 파라미터는 &로 구분한다.

class _HttpApp extends State<HttpApp> { String result = ''; List? data; @override void initState() { super.initState(); data = new List.empty(growable: true); } @override Widget build(BuildContext context) { (...생략...) Future<String> getJSONData() async { var url = 'https://dapi.kakao.com/v3/search/book?target=title&query=doit'; var response = await http.get(Uri.parse(url)), headers: {"Authorization": "KakaoAK 3f9ebc77f4d85936ab9aba99db774751" setState(() { var dataConvertedToJSON = json.decode(response.body); List result = dataConvertedToJSON['documents']; data!.addAll(result); }); return response.body; } }

👉🏻 데이터를 리스트 형태로 저장한다.

 body: Container( child: Center( child: data!.length == 0 ? Text( '데이터가 없습니다.', style: TextStyle(fontSize: 20), textAlign: TextAlign.center, ) :ListView.builder( itemBuilder: (context, index) { return Card( child: Container( child: Column( children: <Widget>[ Text(data![index]['title'].toString()), Text(data![index]['authors'].toString()), Text(data![index]['sale_price'].toString()), Text(data![index]['status'].toString()), Image.network( data![index]['thumbnail'], height: 100, width: 100, fit: BoxFit.contain, ) ], ), ), ); }, itemCount: data!.length,

👉🏻 build함수에서 ListView를 이용해 리스트 형태로 화면에 출력한다.
✍🏻 Image.network: 네트워크에 있는 이미지를 가져온다.

 

카드 위젯 꾸미기

 

 :ListView.builder( itemBuilder: (context, index) { return Card( child: Container( child: Row( children: <Widget>[ Image.network( data![index]['thumbnail'], height: 100, width: 100, fit: BoxFit.contain, ), Column( children: <Widget>[ Container( width: MediaQuery.of(context).size.width - 150, child: Text( data![index]['title'].toString(), textAlign: TextAlign.center, ), ), Text('저자 : ${data![index]['authors'].toString()}'), Text('가격 : ${data![index]['sale_price'].toString()}'), Text('판매중 : ${data![index]['status'].toString()}'), ], ) ], mainAxisAlignment: MainAxisAlignment.start, ), ), );

👉🏻 Row를 사용해 책 그림과 책 제목을 한 행에 넣어준다.
✍🏻 MediaQuery.of(context).size: 지금 스마트폰의 화면 크기, 스마트폰별로 화면 크기가 달라서 절대적 크기가 아닌 상대적인 크기를 사용한다.

 

 

검색 기능 추가하기

📌 사용자가 원하는 책을 검색해서 볼 수 있게 만들자!

 title: TextField( controller: _editingController, style: TextStyle(color: Colors.white), keyboardType: TextInputType.text, decoration: InputDecoration(hintText: '검색어를 입력하세요'), ), ),

👉🏻 title에 텍스트필드를 넣어 검색창을 만든다.
✍🏻 decoration: 텍스트 필드 위젯에 보이는 텍스트를 꾸민다. hintText는 사용자에게 무엇을 입력해야 하는지 알려준다.

 Future<String> getJSONData() async { var url = 'https://dapi.kakao.com/v3/search/book?' 'target=title&query=${_editingController!.value.text}';

👉🏻 url 수정

 

스크롤로 책 정보 가져오기

📌 스크롤을 내릴 때 마다 이어서 새로운 책을 받아서 표시한다. (한 번에 데이터 받기x)

 var url = 'https://dapi.kakao.com/v3/search/book?' 'target=title&page=$page&query=${_editingController!.value.text}';

👉🏻 페이지 단위로 불러오도록 url 수정한다.

class _HttpApp extends State<HttpApp> { String result = ''; List? data; TextEditingController? _editingController; ScrollController? _scrollController; int page = 1; @override void initState() { super.initState(); data = new List.empty(growable: true); _editingController = new TextEditingController(); _scrollController = new ScrollController(); _scrollController!.addListener(() { if (_scrollController!.offset >= _scrollController!.position.maxScrollExtent && _scrollController!.position.outOfRange) { print('bottom'); page++; getJSONData(); } }); }

👉🏻 목록 가장 밑으로 내리면 page 숫자를 증가시키고 서버에 다시 요청하도록 한다.
✍🏻 offset: 목록에서 현재 위치를 double형 변수로 나타낸다. 스크롤할 때마다 이 값을 검사해 maxScrollExtent보다 크거나 같고 스크롤 컨트롤러의 position에 정의된 변수를 넘어가지 않으면 목록의 마지막이라고 인식한다. 그러면 page를 1 증가시키고 getJSONData 함수를 실행한다.

 controller: _scrollController,

👉🏻 ListView.build 함수의 controller 옵션에 입력한다.

 floatingActionButton: FloatingActionButton( onPressed: () { page = 1; data!.clear(); getJSONData(); },

👉🏻 async를 삭제하고 버튼 누를 때마다 기존 내용을 지우고 페이지를 1로 초기화하는 코드를 넣는다.



728x90