Flutter는 선언형 UI를 사용하고있기에 상태관리가 매우 중요하다.
기존 xml로 화면을 그린 안드로이드는 textView에 setText();하면 텍스트가 반영되는 구조였지만
선언형 UI에서는 dataBinding이 되어있지만 데이터 변경을 위젯에 알려야한다고 봐야한다.
setState()는 위젯전체를 그리는 방식으로 많은 리소스를 사용하여 비효율적이다.
또한 로직에 따라서 setState()가 무수히 많이 사용되는 경우가 있을 수 있다.
setState를 굳이 사용하지 않고 상태관리를할 수 있는 대표적인 패키지는 GetX, Provider, BLoC, RiverPod가 있다.
오늘은 Provider와 MVVM패턴의 결합을 알아 볼 것이다.
(Model, View, ViewModel구조를 사용하며 Repository, DataSource등을 구현하지 않음)
1. 외부 패키지 provider 추가
provider: ^6.0.5
2. ViewModel 클래스 생성
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../Model/itemListData.dart';
class itemListViewModel extends ChangeNotifier {
late itemListData itemList;
parsingData() async {
final Uri parsingData = Uri.parse("API호출 URI");
final http.Response response = await http.get(parsingData);
Map<String, dynamic> itemListMap = jsonDecode((utf8.decode(response.bodyBytes)));
itemList = ItemListData.fromJson(itemListMap);
notifyListeners();
}
}
앱 매인화면에는 상품리스트 목록이 노출될 예정이다.
itemListData는 dataModel이며, API파싱값을 json-> dart로 사용한다.
ChangeNofitier가 있어야 notifyListeners()가 가능하며 notifyListeners()는 provider위젯에 상태를 변화시킨다.
즉, itemListViewModel.parsingData()함수로 API호출 및 상태관리를 한번에 하는 것이다.
3. Model 클래스 생성
class itemListData {
int? itemCount;
List<productItem>? item;
itemListData({this.itemCount, this.item});
factory itemListData.fromJson(Map<String, dynamic> json) {
return itemListData(
itemCount: json['data']['itemCount'],
item: (json['data']['list'] as List<dynamic>).map((item) => productItem.fromJson(item as Map<String, dynamic>)).toList(),
);
}
}
class productItem {
int? no;
String? title;
String? thumb;
String? id;
int? price;
String? url;
productItem(
{this.no,
this.title,
this.thumb,
this.id,
this.price,
this.url});
factory productItem.fromJson(Map<String, dynamic> json) {
return productItem(
no: json['no'],
title: json['title'],
thumb: json['thumb'],
id: json['id'],
price: json['price'],
url: json['url']);
}
}
다른예제는 int Count를 상태관리하는 예제가 많았지만, 나는 API response를 상태관리하고자한다.
(model클래스는 상태관리할 자료형에 맞춰서 수정하시길바랍니다.)
4. provider사용을 위해 viewModel을 추가
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (BuildContext context) => itemListViewModel()),
//
],
child: const MyApp(),
),
);
해당 배열에 여러개의 provider추가가 가능하며, 누락시 런타임에서 에러가 발생할 수 있다.
5. 함수호출 및 데이터가져오기
(1) initState()에 함수로 itemList를 가져오기
await context.read<itemListViewModel>().parsingData();
itemList = context.read<itemListViewModel>().itemList;
(2) Widget build에서 적용
Text(
// Provider 내에서 관리하는 count 데이터 관찰
'${context.watch<itemListViewModel>().itemList.count}’
)
여기까지면 Provider, API, MVVM 적용이 완료되었다.
'Flutter' 카테고리의 다른 글
[Flutter] workManager (0) | 2024.08.26 |
---|---|
[Flutter] 대량 네트워크 이미지의 로딩 (2) | 2024.07.24 |
[Flutter] Firebase - Crashlytics PlatformDispatcher (최종) (0) | 2024.06.27 |
[Flutter] InAppWebView - useShouldInterceptRequest가 발생시킨 ANR (0) | 2024.06.21 |
[Flutter] InAppWebView - 뒤로가기 (0) | 2024.06.18 |