플러터 통신2 (v-vm-repo 역할) ★★★

김인범's avatar
Jan 13, 2025
플러터 통신2 (v-vm-repo 역할) ★★★

Provider / vm 구조에서 통신

📌
view (그림 그리기)
View Model (상태관리, 비즈니스로직, 파싱)
Repository (통신)

main

import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'future_page.dart'; import 'home_page.dart'; void main() { runApp(ProviderScope(child: MyApp())); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: HomePage(), ); } }
runApp에 ProviderScope 달아준다.

home_page

import 'package:flutter/material.dart'; import 'home_body.dart'; class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: HomeBody(), ); } }
body에 HomeBody( ) 만들어준다.

home_body 작성 전에 home_page_vm 만들어준다.

import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mockapp/home_repository.dart'; final homeProvider = NotifierProvider<HomePageVM, int?>(() { return HomePageVM(); }); class HomePageVM extends Notifier<int?> { HomeRepository repo = const HomeRepository(); // 상태 @override int? build() { // 상태 초기화 시작 getOne(); // 초기화 여기서 vm 빌드에서 // 상태 null 초기화 return null; } // 행위 Future<void> getOne() async{ int one = await repo.getOne(); state = one; } }
VM은 Repository를 의존한다!!
상태 초기화 시 >> repo의 getOne( ) 실행
getOne 은 비동기 함수로 repo에서 실행시키고 바로 튀어나온다.
 

home_repository만들기

// SRP : 데이터를 가져오는 곳 // (휴대폰 디바이스(파일), 휴대폰 DB, Firebase(외부서버), 내 서버, 공공데이터서버) class HomeRepository { const HomeRepository(); // 반환 타입 Future<실제 받을 반환타입> <-형태 기억하기 Future<List<int>> getList() async { // 비동기 / response는 promise데이터 List<int> response = await Future.delayed(Duration(seconds: 3), () { // 3초 후 실행됨.. return [1,2,3,4]; },); return response; } Future<int> getOne() async{ int response = await Future.delayed(Duration(seconds: 3), () { // 3초 후 실행됨.. return 5; },); return response; } }
repository에서는 모든 것들이 비동기로 실행되고,
Future<실제 반환 타입> 함수명( ) async { } 형태로 이루어진다.
◎ 실제 반환 타입이 없더라도 Future<void> 함수명( ) async로 기재해야한다.
 

home_body

import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mockapp/home_page_vm.dart'; import 'package:mockapp/home_repository.dart'; class HomeBody extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { int? one = ref.watch(homeProvider); if(one == null){ return Center(child: CircularProgressIndicator()); }else{ return Column( children: [ Center(child: Text("$one", style: TextStyle(fontSize: 50))), Expanded( child: ListView.builder( itemCount: 4, itemBuilder: (context, index) { return ListTile(leading: Text("${index + 1}"),title: Text("내용")); }), ), ], ); } } }
int? one = ref.watch(homeProvider); 코드를 통해 provider가 창고(VM)을 만든다.
이때 창고에 있는 상태는 통신을 통해 가져오는데,
home_page_vm에서
notion image
초기 상태는 null 값이 된다.
이 null 값일 때 화면을 처리하기 위해서 if( )else( )를 사용해서 처리를 한다.
int? one = repo.watch(homeProvider); << int? 로 받는 이유
 
if(one == null){ return Center(child: CircularProgressIndicator()); }else{ return Column( children: [ Center(child: Text("$one", style: TextStyle(fontSize: 50))), Expanded( child: ListView.builder( itemCount: 4, itemBuilder: (context, index) { return ListTile(leading: Text("${index + 1}"),title: Text("내용")); }), ), ], );
만약 지켜보고 있는 상태(one)가 null 일 경우
View는 CircularProgressIndicator()화면에 그리게 된다.
통신을 통해 데이터가 들어와 null이 아니라면
else의 Column 그림이 그려지게 된다.
 
 
Share article

taker