728x90
온라인 강좌를 듣고 Provider 상태관리를 Riverpod 로 변경해보고 있다.
구글 검색으로 많이 나오는 Todo 에 예제와 비슷한 예제이다.
import 'package:bucket_list/view/home_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(
ProviderScope(
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: HomePage(),
);
}
}
|
import 'package:bucket_list/provider/bucket_provider.dart';
import 'package:bucket_list/view/create_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class HomePage extends ConsumerStatefulWidget {
const HomePage({super.key});
@override
ConsumerState<HomePage> createState() => _HomePageState();
}
class _HomePageState extends ConsumerState<HomePage> {
@override
Widget build(BuildContext context) {
final bucketList = ref.watch(bucketProvider);
return Scaffold(
appBar: AppBar(
title: Text("버킷 리스트"),
centerTitle: true,
),
body: bucketList.isEmpty
? Center(child: Text("버킷 리스트를 작성해 주세요."))
: ListView.builder(
itemCount: bucketList.length, // bucketList 개수 만큼 보여주기
itemBuilder: (context, index) {
final bucket = bucketList[index]; // index에 해당하는 bucket 가져오기
return ListTile(
// 버킷 리스트 할 일
title: Text(
bucket.job,
style: TextStyle(
fontSize: 24,
color: bucket.isDone ? Colors.grey : Colors.black,
decoration: bucket.isDone
? TextDecoration.lineThrough
: TextDecoration.none,
),
),
// 삭제 아이콘 버튼
trailing: IconButton(
icon: Icon(CupertinoIcons.delete),
onPressed: () {
// 삭제 버튼 클릭시
showDeleteDialog(context, index);
},
),
onTap: () {
bucket.isDone = !bucket.isDone;
//bucketService.updateBucket(bucket, index);
ref.read(bucketProvider.notifier).updateBucket(bucket);
},
);
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () async {
// + 버튼 클릭시 버킷 생성 페이지로 이동
String? job = await Navigator.push(
context,
MaterialPageRoute(builder: (_) => CreatePage()),
);
},
),
);
}
void showDeleteDialog(
BuildContext context, int index) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("정말로 삭제하시겠습니까?"),
actions: [
// 취소 버튼
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("취소"),
),
// 확인 버튼
TextButton(
onPressed: () {
//bucketService.deleteBucket(index);
ref.read(bucketProvider.notifier).deleteBucket(index);
Navigator.pop(context);
},
child: Text(
"확인",
style: TextStyle(color: Colors.pink),
),
),
],
);
},
);
}
}
|
import 'package:bucket_list/provider/bucket_provider.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class CreatePage extends ConsumerStatefulWidget {
const CreatePage({super.key});
@override
ConsumerState<CreatePage> createState() => _CreatePageState();
}
class _CreatePageState extends ConsumerState<CreatePage> {
// TextField의 값을 가져올 때 사용합니다.
TextEditingController textController = TextEditingController();
// 경고 메세지
String? error;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("버킷리스트 작성"),
// 뒤로가기 버튼
leading: IconButton(
icon: Icon(CupertinoIcons.chevron_back),
onPressed: () {
Navigator.pop(context);
},
),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
// 텍스트 입력창
TextField(
controller: textController, // 연결해 줍니다.
autofocus: true,
decoration: InputDecoration(
hintText: "하고 싶은 일을 입력하세요",
errorText: error,
),
),
SizedBox(height: 32),
// 추가하기 버튼
SizedBox(
width: double.infinity,
height: 48,
child: ElevatedButton(
child: Text("추가하기", style: TextStyle(fontSize: 18)),
onPressed: () {
// 추가하기 버튼 클릭시
String job = textController.text; // 값 가져오기
if (job.isEmpty) {
setState(() {
error = "내용을 입력해주세요."; // 내용이 없는 경우 에러 메세지
});
} else {
setState(() {
error = null; // 내용이 있는 경우 에러 메세지 숨기기
});
// BucketService 가져오기
//BucketService bucketService = context.read<BucketService>();
//bucketService.createBucket(job);
ref.read(bucketProvider.notifier).createBucket(job);
Navigator.pop(context, job); // job 변수를 반환하며 화면을 종료합니다.
}
},
),
),
],
),
),
);
}
}
|
/// 버킷 클래스
class Bucket {
String id;
String job; // 할 일
bool isDone; // 완료 여부
Bucket(this.id, this.job, this.isDone); // 생성자
}
|
import 'package:bucket_list/model/bucket.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final bucketProvider = NotifierProvider<BucketNotifier, List<Bucket>>(BucketNotifier.new);
class BucketNotifier extends Notifier<List<Bucket>> {
@override
List<Bucket> build() => [];
/// bucket 추가
void createBucket(String job){
state = [...state, Bucket((state.length + 1).toString(),job, false)];
}
/// bucket 수정
void updateBucket(Bucket bucket){
state = [
for(final item in state)
if(item.id == bucket.id)
Bucket(item.id, bucket.job, bucket.isDone)
else
item
];
}
/// bucket 삭제
void deleteBucket(int index){
//state = state.where((e) => e.id != bucket.id).toList(); // Bucket bucket 인자로 받을 때
state = List.from(state)..removeAt(index);
}
}
|
Riverpod Notifier로 구현한 코드와
Provider 로 구현한 BucketService 코드를
비교해서 보면 도움이 될 거 같다.
import 'package:burket_list/model/bucket.dart';
import 'package:flutter/material.dart';
class BucketService extends ChangeNotifier {
List<Bucket> bucketList = [];
/// bucket 추가
void createBucket(String job){
bucketList.add(Bucket(job, false));
notifyListeners();
}
/// bucket 수정
void updateBucket(Bucket bucket, int index){
bucketList[index] = bucket;
notifyListeners();
}
/// bucket 삭제
void deleteBucket(int index){
bucketList.removeAt(index);
notifyListeners();
}
}
/***
* 전역적으로 사용되는 데이터를 담당할 서비스를 만들고,
* 해당 데이터에 대한 CRUD를 모두 해당 서비스에서 구현한다.
*/
|
728x90
'Flutter 앱 > 상태관리' 카테고리의 다른 글
Flutter riverpod 자동 생성 (0) | 2024.01.15 |
---|---|
Flutter Provider 상태관리 예제 (0) | 2024.01.06 |
Flutter StatefulWidget (0) | 2023.12.13 |
Flutter Riverpod - NotifierProvider.family (0) | 2023.12.11 |
Flutter Riverpod - NotifierProvider (0) | 2023.12.11 |