Flutter 날씨 앱 만들기(3) - 로딩 화면 만들기, API 사용법, API 데이터 받아오기

이번에는 날씨 API을 json 형식으로 받아오는 작업과, 그 앱 계속 동작중이라는 것을 알 수 있도록

로딩화면을 적용해보겠습니다. (만약, 데이터를 받아오는 시간이 오래걸리는데 아무런 애니메이션이나 변화가 없다면 사용자들은 앱이 멈췄다고 생각하겠죠?)

 

https://colalove5562.tistory.com/52?category=1036672

 

Flutter 날씨 앱 만들기(2) - 프로젝트 생성, 위치 권한 확인, 위치정보 받아오기, API Key 발급

1. 폴더 구조 소개 전체 적인 폴더 구조는 사진과 같습니다. 기본적으로 프로젝트를 생성하면 작성되는 main.dart 파일이 있고, data, model, screens 3개의 폴더를 추가로 생성하여 각각의 파일들을 관리

colalove5562.tistory.com


1. 로딩화면 구현을 위한 플러그인 추가하기

 

우선 플로그인을 추가해보도록 하겠습니다.

https://pub.dev/packages/flutter_spinkit

 

flutter_spinkit | Flutter Package

A collection of loading indicators animated with flutter. Heavily inspired by @tobiasahlin's SpinKit.

pub.dev

플러터의 다양한 로딩 애니메이션 효과

사이트에 접속해보시면 위 사진과 같이 다양한 애니메이션을 제공합니다.

(플러터를 공부하면 할수록 정말 편리하고 좋구나를 새삼 느끼고 있습니다.. ^^)

Versions 에서 Installing 버전과 Import 코드를 복사해서 프로젝트에 추가해줍니다. 코드는 아래와 같습니다.

 

pubspec.yaml 파일에 추가 (앞으로 필요할 다른 플러그인들도 미리 추가합니다!)

만약, 플러그인의 버전정보가 맞지 않는다면 https://pub.dev/ 에서 적절한 버전으로 수정해주면 됩니다.

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2

  # 권한 확인
  permission_handler: ^8.3.0

  # 위치 관련 패키지
  geolocator: ^8.0.5

  # 로딩 라이브러리
  flutter_spinkit: ^5.1.0
  
  # http 통신
  http: ^0.13.4

 

 

2. loading.dart 수정

지난번 생성한 loading.dart 파일을 열고, build 부분을 다음과 같이 변경해줍니다.

물론, 최상단 spinkit 을 import 해주는 것도 잊지말고 적어주세요!

import 'package:flutter_spinkit/flutter_spinkit.dart';

  /* 중간 코드 생략 */

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color(0xffF49B33), //Colors.amber
      body: Center(
        child: SpinKitFadingCircle(
          color: Colors.white,
            size: 80.0,
        ),
      ),
    );
  }

 

이제 여기까지만 작성하고 앱을 실행시켜보면, 계속 돌아가는 로딩화면이 보이게 됩니다.

당연하게도 main.dart 에서 Loding() 페이지로 넘어오고, loading페이지에서 화면을 보여주겠다~ 라고만 했기 때문이죠!

 

이제 로딩화면이 동작하는 동안 날씨 API를 통해서 정보를 요청해서 받아오면, 자동으로 다음 화면으로 넘어가는 코드를 작성해보겠습니다.

 

 

3. loading.dart 수정 : 위치정보를 이용해서 날씨 API 요청하기

  const WEATHER_API_KEY = '';  // 발급받은 개인 API KEY 값을 입력해주세요.
  const WEATHER_API_KEY = '';  // 위와 동일.
  
  late double latitude3;
  late double longitude3;

  @override
  void initState() {
    super.initState();
    getLocation();
  }
  
  void getLocation() async {

    // 앞 포스팅에서 만들었던 위치정보 클래스 사용
    MyLocation myLocation = MyLocation();
    await myLocation.getMyCurrentLocation();

    // 받아온 위치(위, 경도 값)을 변수에 저장
    latitude3 = myLocation.latitude2;
    longitude3 = myLocation.longitude2;

    // 네트워크 인스턴스 영역
    Network network = Network('https://api.openweathermap.org/data/2.5/weather?lat=$latitude3&lon=$longitude3&appid=$WEATHER_API_KEY&units=metric',
        'https://api.openweathermap.org/data/2.5/air_pollution?lat=$latitude3&lon=$longitude3&appid=$WEATHER_API_KEY');
  } // ...getLocation()

여기가 까지만 작성하면 당..연히! 에러가 발생합니다. Network 파일 내용을 작성하지 않았기 때문에...

크게 어려운 부분이 없기 때문에 바로 다음 코드를 작성해보겠습니다.

 

 

4. Network 파일 생성

import 'package:http/http.dart' as http_pk;
import 'dart:convert'; // jsonDcode 사용 가능

class Network{

  late final String url; // 날씨정보
  late final String url2; // 미세먼지(기상정보)

  // 생성자 : 앞 loading 코드에서 보낸 주소를 받습니다.
  Network(this.url, this.url2);

  Future<dynamic> getJsonData() async{
    http_pk.Response response = await http_pk.get(Uri.parse(url));

    if(response.statusCode == 200) {
      String jsonData = response.body;
      var parsingData = jsonDecode(jsonData);

      return parsingData;
    } else{
      // 예외상황 처리
    }
  } // ...getJsonData()

  Future<dynamic> getAirData() async{
    http_pk.Response response = await http_pk.get(Uri.parse(url2));
    if(response.statusCode == 200) {
      String jsonData = response.body;
      var parsingData = jsonDecode(jsonData);

      return parsingData;
    } else{
      // 예외상황 처리
    }
  } // ...getAirData()

}

우선 생성자를 통해, 앞 loading 파일에서 넘어오는 주소를 받아줍니다.

(여기서 주소는, API를 요청하기 위한 주소로 날씨를 요청하기 위한 위치정보 + API KEY 값이 포함되어 있습니다.)

 

- getJsonData() : 날씨정보를 요청, 결과 받기

- getAirData() : 미세먼지 정보를 요청, 결과 받기

 

혹시 데이터 통신에 실패했을때 동작할 예외상황은 별도로 작성하지 않았습니다.

(실패했을 경우? => 데이터 재 요청, 실패시 그에 맞는 팝업 메시지 동작 등....)

 

 

5. loading.dart 추가

void getLocation() async {

    /* 위 코드 생략 */
    Network network = Network('https://api.openweathermap.org/data/2.5/weather?lat=$latitude3&lon=$longitude3&appid=$WEATHER_API_KEY&units=metric',
        'https://api.openweathermap.org/data/2.5/air_pollution?lat=$latitude3&lon=$longitude3&appid=$WEATHER_API_KEY');

    // 새로 추가되는 부분
    var weatherData = await network.getJsonData();
    var airData = await network.getAirData();
    
    // 메인페이지로 넘어가는 코드 작성 예정
    // ....
  } // ...getLocation()

위에 작성했던 Network 아래에 코드를 새로 추가합니다.

위 쪽에서 작성해서 return 받은 Json 형식의 데이터를 파싱합니다.

 

이제 메인화면에 표시할 모든 데이터를 받아오는 과정이 끝났습니다.

다음포스팅을 마지막으로 UI 구성 및, 앞에서 받아온 데이터를 표시하는 일을 해보겠습니다!