내배캠 30일차_Flutter 실무숙련(MVVM)


 1. Flutter 실무숙련



RiverPod 패키지 추가 -> 터미널에 flutter pub add flutter_riverpod 




main 함수에서 최상위 위젯을 ProviderScope로 감싸기 (main.dart)

void main() {
runApp(ProviderScope(child:MyApp()));



Widget 구현 (main.dart)

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(home: HomePage());
}
}



데이터를 담을 Model 클래스 만들기(user.dart)

/*
{
"name": "jiwon",
"age": 20
}
*/

class User {
String name;
int age;
User({required this.name, required this.age});

// 1. 네임드 생성자 (fromJson)
User.fromJson(Map<String, dynamic> map)
: this(name: map['name'], age: map['age']);

// 2. toJson 메서드
Map<String, dynamic> toJson() {
return {'name': name, 'age': age};
}
}



모델 가져오는 Repository 클래스 만들기 (User_Repository.dart)

import 'dart:convert';
import 'package:flutter_riverpod_mvvm/user.dart';

class UserRepository {
//
Future<User> getUser() async {
await Future.delayed(Duration(seconds: 1));
String dummy = """
{
"name": "jiwon",
"age": 20
}
""";
// 1. JsonDecode 함수 사용해서 Map으로 변환
Map<String, dynamic> map = jsonDecode(dummy);
// 2. map을 객체로 변환
return User.fromJson(map);
}
}



Widget에서 관리될 상태 클래스 만들기 (home_page.dart)

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_riverpod_mvvm/home_view_model.dart';

class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {

return Scaffold(
appBar: AppBar(),




상태를 관리할 ViewModel 만들기 (Notifier 상속) (home_view_model.dart)

- 최초 상태 build 메서드 재정의 해서 설정

- Repository에서 데이터를 가져와서 상태 업데이트 하는 함수 작성

ViewModel을 공급할 viewModelProvider(NotifierProvider 객체) 만들기 (home_view_model.dart)

// 1. 관리해야 될 상태 클래스 만들기
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_riverpod_mvvm/user.dart';
import 'package:flutter_riverpod_mvvm/user_repository.dart';

class HomeState {
User? user;
HomeState(this.user);
}

// 2. 뷰모델 만들기. Notifier
class HomeViewModel extends Notifier<HomeState> {
@override
HomeState build() {
return HomeState(null);
}

void getUser() async {
UserRepository userRepository = UserRepository();
User user = await userRepository.getUser();
state = HomeState(user);
//state.user = user; => 이렇게 사용하면 위젯에 알려주지 않음
}
}

// 3. 뷰모델을 위젯에게 공급해줄 관리자 만들기
final homeViewModelProvider = NotifierProvider<HomeViewModel, HomeState>(() {
return HomeViewModel();
});




widget에서 Consumer 위젯 사용해서 데이터 씌우기 및 함수 연결 (home_page.dart)

- 상태 업데이트 될 때 위젯이 변경되길 원하면 ref.watch

- 한번만 값을 받아오고 싶으면 ref.read

- viewModel의 메서드를 사용하고 싶으면 ref.read에 viewModelProvider.notifier 넘겨주기


body: Consumer(
builder: (context, ref, child) {
final homeState = ref.watch(homeViewModelProvider);
return Column(
children: [
Text('name: ${homeState.user?.name}'),
Text('name: ${homeState.user?.age}'),
ElevatedButton(onPressed: () {
///
final viewModel = ref.read(homeViewModelProvider.notifier);
viewModel.getUser();
}, child: Text('데이터 가져오기')),
],
);
},
)
);
}
}



ViewModel로 사용할 수 있는 Notifier 종류

Notifier : 참고하기 시작하면 앱이 종료될 때 까지 유지 ex. 로그인 시 회원정보 같이 앱 전반적으로 사용되는 상태를 관리할 때 주로 사용


AutoDisposeNotifier

참조하기 시작한 시점부터 처음 참조한 위젯이 화면에서 없어질 때 같이 없어짐.

로그인 페이지 -> 회원가입 페이지 -> 로그인 페이지로 뒤로가기 -> 회원가입 페이지


AutoDisposeFamilyNotifier

위에거랑 동일하나 ViewModel 최초 생성 시, 위젯에서 ViewModel에 값을 넘겨서 무언가를 처리하고 싶을 때

블로그 목록 페이지 -> 블로그 포스트 상세페이지로 이동할 때 어떤 블로그 포스트의 정보를 불러오는지  뷰모델에 넘겨주고 싶을 때?




2. 인사이트 클럽 


책<미니멀리스트 창업가> 사힐 라빈지아 지음, 박재영 옮김, CAPITALEDGE
Chapter.6 성장과 균형의 조화


성장을 회피하거나 비효율적인 시스템을 유지하려는 것이 좋은 선택이 아니다.
(p.224)


지속적인 성장을 하기 위해서는
자금 고갈, 열정/에너지 고갈에 대비해야 한다.

비용을 써야할 곳과 아껴야 할 곳을 판단하는 기준이라면,
'성장과 매출 발생에 직접적으로 도움이 되는지'가 아닐까.
대체할 수 있는 무언가가 있다면 최대한 비용을 아끼는 편이 나을 것이다.







댓글

이 블로그의 인기 게시물

내배캠15일차_map() reduce() fold()

내배캠16일차_Flutter_스토어 앱 만들기

내배캠 [3주차 WIL]