Dart에서 통신(가정)

화낼거양's avatar
Dec 31, 2024
Dart에서 통신(가정)
 
 
💡
통신을 쉽게 관리하기 위해 Dart에서의 통신은 뷰 모델(ViewModel)을 사용합니다. (MVVM패턴)
ViewModelRepository를 통해 데이터를 가져오며, 앱의 상태를 관리합니다. 기본적으로 비동기 요청을 통해 데이터를 가져와서 UI를 업데이트합니다.
 
 
아래의 예제는 Riverpod 라이브러리를 필요로 합니다.

View

 
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mockapp/home_page_vm.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("내용"),); },), ) ], ); } } }
 
  • ConsumerWidget: Riverpod 패키지에서 제공하는 위젯으로, 상태를 구독하고 빌드할 때 사용합니다. WidgetRef 객체를 사용해서 해당 위젯이 구독하고 있는 상태에 접근할 수 있습니다.
  • ref.watch(homeProvider): Riverpod을 통해 homeProvider 상태를 구독하는 부분입니다. 이 코드에서 int? 타입이어야 하는 one 변수를 받아옵니다. 이 변수는 homeProvider의 현재 상태를 나타냅니다.
  • one == null: one 변수가 null인 경우, 이는 아직 데이터가 로드되지 않았음을 의미합니다. 이때, CircularProgressIndicator()를 보여주며 로딩 중임을 사용자에게 알립니다.
  • Column: 데이터가 로드된 후, one 변수는 null이 아니게 됩니다. 이때 Column 위젯을 사용하여 여러 자식을 수직으로 배치합니다.
    • Text("${one}"): one 값을 표시하는 Text 위젯입니다. 이 숫자를 큰 폰트 크기로 표시합니다.
    • Expanded: 남은 화면 공간을 차지하는 ListView 위젯을 포장합니다.
      • ListView.builder: 제공한 itemCount만큼 ListTile을 생성합니다.
 
 

Provider (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(); // 상태 null 초기화 return null; } Future<void> getOne() async { int one = await repo.getOne(); state = one; } } // 위의 내용은 실제로 통신을 한 것이 아닌, 통신을 한 것과 유사하게 작성한 내용입니다.
 
  • homeProvider: 이 부분에서는 NotifierProvider를 사용하여 HomePageVM 클래스의 인스턴스를 제공합니다. NotifierProvider는 Riverpod에서 제공해주는 상태 관리 도구입니다. 상태로 int?를 가지고 있으며, 이는 초기에는 null이 될 수 있음을 의미합니다.
  • HomePageVM 클래스:
    • Notifier<int?>: 이 클래스는 Notifier를 확장하며, 이는 Riverpod에서 제공하는 상태 관리의 기본 단위입니다.
    • HomeRepository repo: HomeRepository 클래스의 인스턴스를 생성합니다. 이 클래스는 데이터를 가져오는 역할을 합니다.
    • @override int? build(): build 메서드는 Notifier 클래스에서 반드시 구현해야 하는 메서드로, 초기 상태를 설정하는 역할을 합니다. 이 메서드 안에서 getOne() 메서드를 호출하여 비동기적으로 데이터를 가져옵니다. build 메서드는 기본적으로 상태를 null로 초기화합니다.
    • Future<void> getOne() async: 이 메서드는 비동기적으로 동작하며 HomeRepository에서 값을 가져오는 역할을 합니다. await을 통해 repo.getOne()을 호출하여 결과를 one 변수에 저장합니다. 그리고 state 변수를 one 값으로 업데이트하여 Notifier의 상태를 변경합니다.
 
 

Repository

 
// SRP : 데이터를 가져오는 곳 (휴다폰 디바이스(파일), 휴대폰 DB, Firebase(외부서버), 내서버, 공공데이터서버) class HomeRepository { const HomeRepository(); // 비동기 요청에서 return 타입은 항상 Future를 붙여야 한다. void의 경우는 Future<void> Future<List<int>> getList() async { 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; } }
 
  • HomeRepository 클래스: const 생성자를 사용하여 클래스의 인스턴스를 상수로 만듭니다. 이는 불변 객체(immutable object)를 생성하여 메모리 효율을 높일 수 있습니다.
 

주요 메서드 설명:

 
  • Future<List<int>> getList():
    • 비동기적으로 작동하며 Future<List<int>>을 반환합니다.
    • await Future.delayed를 사용하여 3초 후에 실행됩니다.
    • 이 메서드는 [1, 2, 3, 4] 리스트를 반환합니다.
  • Future<int> getOne():
    • 비동기적으로 작동하며 `Future<int>을 반환합니다.
    • await Future.delayed를 사용하여 3초 후에 실행됩니다.
    • 이 메서드는 5를 반환합니다.
 
 
 

요약

 
통신이 완료되기 전에는 state 값이 null 이기 때문에 돌아가는 원 모양의 뷰를 확인할 수 있고,
통신이 완료된 후에는 정상적으로 의도한 컬럼요소가 출력될 것 입니다.
 
 
통신 완료 전 (3초 이전) :
notion image
 
통신 완료 후 (3초 후) :
notion image
Share article

moohyun