<Flutter> 플러터 통신

yezee·2024년 4월 9일
0

Flutter

목록 보기
3/15
post-thumbnail

stateful widget으로 비동기 api처리하기

pub.dev에서 http패키지 다운

URL생성
생성한 URL을 사용하여 http get요청을 보냄
http응답에서 받은 데이터를 JSON형식으로 디코딩하여 변수에 저장
객체로 변환하여 반환
배열로 받기위해서는 객체를 배열에 for문으로 add

import 'dart:convert';
import 'package:http/http.dart' as http; //http요청을 도와주는 패키지를 http로 명시
import 'package:webtoon/models/webtoon_model.dart';

class ApiService {
  final String baseUrl = "https://webtoon-crawler.nomadcoders.workers.dev";
  final String today = "today";

 Future<List<WebtoonModel>> getTodaysToons() async {
    List<WebtoonModel> webtoonInstances = [];
    final url = Uri.parse("$baseUrl/$today"); //URL을 생성
    final response = await http.get(url); //생성한 URL을 사용하여 http get요청을 보냄
        
    if (response.statusCode == 200) {
      final List<dynamic> webtoons = jsonDecode(response.body); //http응답에서 받은 데이터를 JSON형식으로 디코딩하여 변수명으로 저장
      for (var webtoon in webtoons) {
        webtoonInstances.add(WebtoonModel.fromJson(webtoon));
        //fromJson이라는 named constructor을 사용해서 webtoonModel을 만들어준다
      }
      return webtoonInstances;
    }
    throw Error();
  }
}

models클래스를 만들어서 코드를 관리하는 이유

  • 데이터모델링- 데이터의 구조와 속성을 명확하게 정의
  • 코드응집성- 데이터와 관련된 로직을 하나의 단일 클래스로 묶어준다
  • JSON파싱- 주로 외부 api는 JSON형식으로 데이터를 받아온다, 이때 json데이터를 model클래스로 변환하여 사용하면 데이터의 구조를 명확히 알수있고,json파싱 작업을 간편하게 가능
  • 타입안정성- 데이터 타입을 명시적으로 지정해서 코드에서 발생할수있는 타입관련 오류를 사전에 방지
  • 유지보수성- 데이터구조가 변경되거나 추가될 경우, Model클래스만 수정하면 되므로 코드 유지보수성 향상
//named constructor
//constructor의 인수만 적어주고, property를 적어주면 초기화할 수 있어서 편리

class WebtoonModel {
  final String title, thumb, id;

  WebtoonModel.fromJson(Map<String, dynamic> json)
      : title = json["title"], 
        thumb = json["thumb"],
        id = json["id"];
}

statefuleWidget 을 사용해서
비동기처리 api,setstate,isLoading을 처리할 수 있다

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

  
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  List<WebtoonModel> webtoons = [];
  bool isLoading = true;

  void waitForWebToons() async {
    webtoons = await ApiService.getTodaysToons();
    isLoading = false;
    setState(() {});
  }

  
  void initState() {
    //빌드를 하기 전에 먼저 실행(lifecycle)
    super.initState();
    waitForWebToons();
  }

  
  Widget build(BuildContext context) {
}

FutureBuilder를 사용하면 stateless 위젯으로 비동기처리 api를 가져올 수 있어요~!

FutureBuilder
FutureBuilder를 사용하면 stateless 위젯으로 비동기처리 api를 가져올 수 있어요~!
await,setstate,isLoading을 한번에 해결해주는 위젯

  1. Future생성
  2. FutureBuilder에 넣기

spanshot을 이용하면 future의 상태를 알수있다
futureBuilder는 future랑 builder()를 받는다
future-> 기다릴 Future를 작성
builder함수-> context와 snapshot을 전달받는다
(*스냅샷은 future의 상태를 알수있다)

listView
여러항목을 나열하는데 최적화된 widget
listView.builder
인덱스를 통해 어떤 아이템이 build되는지 알 수 있다
사용자가 보고 있는 아이템만 build해줄수있다(메모리효율을 높여준다)

  final Future<List<WebtoonModel>> webtoons = ApiService.getTodaysToons()

body: FutureBuilder(
        future: webtoons,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
              scrollDirection: Axis.horizontal,
              itemCount: snapshot.data!.length,
              itemBuilder: (context, index) {
                
                var webtoon = snapshot.data![index];
                return Text(webtoon.title);
              },
            );
          }
          return const Center(
            child: CircularProgressIndicator(), //로딩처리
          );
        },
      ),

but,URL에 파라미터가 포함되어있다면 stateless위젯에서 final을 써서 사용할 수 없다

방법1

statefulwidget은 생성자가 호출될때, widget 속성에 해당 statefulwidget의 현재 상태가 자동으로 저장되기때문에 위젯을 통해 state에 접근할 수 있다

class DetailScreen extends StatefulWidget {
  final String title, thumb, id;

  const DetailScreen({
    super.key,
    required this.title,
    required this.thumb,
    required this.id,
  });

  
  State<DetailScreen> createState() => _DetailScreenState();
}

class _DetailScreenState extends State<DetailScreen> {

late Future<WebtoonDetailModel> webtoon;

  
  void initState() {
    super.initState();
    webtoon = ApiService.getToonById(widget.id);
  }

방법2

statelesswidget을 사용하면 객체를 생성하는 생성자 역할을 하지 않기 대문에 퍼로퍼티 초기화를 시킬 수 없다

대신, late키워드를 사용하여 변수를 선언할때 초기화하지 않고, 나중에 값이 필요할때 값을 할당할 수 있다

class DetailScreen extends StatelessWidget {
  final String title, thumb, id;

late final webtoon=ApiService.getToonById(id);

 DetailScreen({
    super.key,
    required this.title,
    required this.thumb,
    required this.id,
  });
profile
아 그거 뭐였지?

0개의 댓글