티스토리 뷰

Mobile/Flutter

[Flutter] API 연동

춘햄 2022. 7. 24. 11:43

기초적인 CRUD를 구성을 완료했으니, 동일한 Todo List 프로젝트에서 News 정보를 가져와 띄워줄 수 있도록 HTTP 방식으로 구현된 API를 연동해보도록 하자.

 

사실 Native와 Java에서 많이 다루기도 했고, 그닥 어려운 내용 없이 Http 패키지를 사용하는 방법이 전부지만, 그래도 한번 다루고 넘어가는 게 좋을 거 같다.

 

바로 확인해보자.


우선 News 정보를 가져와야 하니, https://newsapi.org/ 에서 로그인 후 API Key를 발급 받았다. API Doc 이나 사용법은 해당 페이지에 자세하게 설명이 되어 있으니, 참고하도록 하자.

 

이제  HTTP 요청을 처리해야 하니, 해당 패키지를 dependency에 추가해주자.

 

◎pubspec.yaml

# HTTP 
http: ^0.13.3

 

다음으로 news를 관리할 model 객체를 만들어야 한다.

 

◎news.dart

class News {
  late String title;
  late String description;

  News ({
    required this.title,
    required this.description
  });

  News.fromMap(Map<String, dynamic>? map) {
    title = map?['title'];
    description = map?['description'];
  }
}

 

이제 데이터를 가져와 news 객체 배열을 만들 repository를 작성하자.

 

◎newsRepository.dart

 


import 'dart:convert';
import 'dart:developer';

import '../models/news.dart';
import 'package:http/http.dart' as http;

class NewsRepository {
  static String apiUrl =
      'https://newsapi.org/v2/top-headlines?country=kr&apiKey=';
  static String apiKey = 'API 키를 삽입하세요';

  Uri uri = Uri.parse(apiUrl + apiKey);

  Future<List<News>> getNews() async {
    List<News> news = [];
    final response = await http.get(uri);
    final statusCode = response.statusCode;
    final body = response.body;

    log(statusCode.toString());

    if(statusCode == 200) {
      news = jsonDecode(body)['articles'].map<News> ((article) {
        return News.fromMap(article);
      }).toList();
    }

    return news;
  }
}

jsonDecode를 사용하여 articles 를 전부 List 형태로 뽑고, List 의 map 메서드를 돌려서 List element 를 하나씩 News 객체로 변경 후에 다시 List 로 생성한다. 

 

map 메서드가 조금 생소할 수 있는데, 이는 여기에서 확인할 수 있다.

 

마지막으로 해당 News List를 얻어와서 화면에 뿌려줄 news_screen 을 작성해주면 완성이다.

 

◎news_screen.dart


import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:todo_list/%20providers/newsRepository.dart';

import '../models/news.dart';

class NewsScreen extends StatefulWidget{
  @override
  _NewsScreenState createState() => _NewsScreenState();
}

class _NewsScreenState extends State<NewsScreen> {
  List<News> news = [];
  bool isLoading = true;
  NewsRepository newsRepository = NewsRepository();

  Future initNews() async {
    news = await newsRepository.getNews();
  }

  @override
  void initState() {
    super.initState();
    initNews().then((value) {
      setState(() {
        isLoading = false;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('뉴스 화면')
      ),
      body: isLoading?
          Center(child: const CircularProgressIndicator()) :
          GridView.builder(
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                childAspectRatio: 2 / 3, // width, height 비율
                crossAxisSpacing: 20,
                mainAxisSpacing: 20
              ),
              itemCount: news.length,
              itemBuilder: (context, index) {
                return Container(
                  padding: EdgeInsets.all(10),
                  child: Column(
                    children: [
                      Text(
                        news[index].title,
                        style: TextStyle(fontSize: 18),
                      ),
                      Text(
                        news[index].description,
                        maxLines: 3,
                        overflow: TextOverflow.ellipsis,
                        style: TextStyle(fontSize: 16),
                      )
                    ],
                  ),
                );
              }
          )
    );
  }

}

 

 

 

끝!!

반응형

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

[Flutter] 전역 상태 관리 기법: Provider  (0) 2022.07.26
[Flutter] 전역 상태 관리 기법: Bloc  (0) 2022.07.25
[Flutter] State  (0) 2022.07.11
[Flutter] 화면 전환  (0) 2022.07.09
[Flutter] Buttons  (0) 2022.07.09
Comments