-
[FLUTTER] 상태 관리 패키지 (Provider) 사용법 정리Flutter 2023. 4. 9. 18:57
1. 전역적으로 사용되는 데이터를 담당할 서비스로 만들고, 해당 데이터에 대한 CRUD를 모두 해당 서비스에서 구현한다.
ChangeNotifier를 상속받아야 notifyListeners(); 를 호출하여 데이터를 사용하는 화면을 갱신할 수 있다.
class BucketService extends ChangeNotifier { void deleteBucket(int index) { bucketList.removeAt(index); notifyListeners(); // Consumer의 builder 함수를 호출하여 화면 갱신 } }
2. Provider 패키지를 이용하여 최상단 위젯 서비스를 등록을 해준다.
[위젯트리 꼭대기에 있는 Provider로 등록한 클래스에 접근 방법]
1. Consumer<클래스명> : 클래스 정보 갱신시 함께 새로고침 할 때 사용
2. context.read<클래스명> : 1회성으로 클래스 접근할 때 사용
- Consumer<클래스명> : 클래스 정보 갱신시 함께 새로고침 할 때 사용
: 서비스에서 notifyListners()를 호출 하는 경우 Consumer의 builder가 호출되며 자동으로 화면이 갱신
- context.read<클래스명> : 1회성으로 클래스 접근할 때 사용
:갱신될 필요 없이, 일회성으로 서비스에 접근하고 싶은 경우, context.read<클래스명>();와 같은 형태로 접근할 수 있다.
[최종코드]
- main
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'bucket_service.dart'; void main() { runApp( MultiProvider( // 위젯트리 꼭대기에 서비스를 등록할때 쓰는 Provider의 문법 providers: [ ChangeNotifierProvider(create: (context) => BucketService()), ], child: const MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: HomePage(), ); } } /// 버킷 클래스 class Bucket { String job; // 할 일 bool isDone; // 완료 여부 Bucket(this.job, this.isDone); // 생성자 } /// 홈 페이지 class HomePage extends StatelessWidget { const HomePage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Consumer<BucketService>(builder: (context, bucketService, child) { // bucketService로 부터 bucketList 가져오기 List<Bucket> bucketList = bucketService.bucketList; return Scaffold( appBar: AppBar( title: Text("버킷 리스트"), ), body: bucketList.isEmpty ? Center(child: Text("버킷 리스트를 작성해 주세요.")) : ListView.builder( itemCount: bucketList.length, // bucketList 개수 만큼 보여주기 itemBuilder: (context, index) { var 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: () { // 삭제 버튼 클릭시 bucketService.deleteBucket(index); }, ), onTap: () { // 아이템 클릭시 bucket.isDone = !bucket.isDone; bucketService.updateBucket(bucket, index); }, ); }, ), floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () { // + 버튼 클릭시 버킷 생성 페이지로 이동 Navigator.push( context, MaterialPageRoute(builder: (_) => CreatePage()), ); }, ), ); }); } } /// 버킷 생성 페이지 class CreatePage extends StatefulWidget { const CreatePage({Key? key}) : super(key: key); @override State<CreatePage> createState() => _CreatePageState(); } class _CreatePageState extends State<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); Navigator.pop(context); // 화면을 종료합니다. } }, ), ), ], ), ), ); } }
- bucket_service.dart
import 'package:flutter/material.dart'; import 'main.dart'; /// Bucket 담당 class BucketService extends ChangeNotifier { // 변경된사항을 알려준다 (notifier) List<Bucket> bucketList = [ Bucket('잠자기', false), // 더미(dummy) 데이터 ]; /// bucket 추가 void createBucket(String job) { // create화면에서 추가하기 버튼을 누를때 호출할것 bucketList.add(Bucket(job, false)); notifyListeners(); // 갱신 = Consumer<BucketService>의 builder 부분만 새로고침 } /// bucket 수정 void updateBucket(Bucket bucket, int index) { // index에 해당되는 bucketList에 전달받은 bucket을 넣는 방식으로 update bucketList[index] = bucket; // 버킷의 상태가 변하는 경우 화면을 갱신하기 위해 notifyListeners()를 호출 notifyListeners(); } /// bucket 삭제 void deleteBucket(int index) { bucketList.removeAt(index); notifyListeners(); } }
- GitHub
https://github.com/Eunice991217/Flutter-ToyProject/tree/main/bucket_list_with_provider
GitHub - Eunice991217/Flutter-ToyProject: Flutter Project Practice
Flutter Project Practice. Contribute to Eunice991217/Flutter-ToyProject development by creating an account on GitHub.
github.com
'Flutter' 카테고리의 다른 글
[Flutter] Could not build module 'WebKit' 해결방법 (0) 2023.09.30 [Flutter] DT_TOOLCHAIN_DIR cannot be used to evaluate LIBRARY_SEARCH_PATHS, use TOOLCHAIN_DIR instead 해결방법 (Xcode 15 Firebase SDK 적용) (0) 2023.09.30 [FLUTTER] 상태 관리 패키지 (Provider) 적용하기 (0) 2023.04.09 [FLUTTER] 상태 관리 패키지 (Provider) 준비하기 (0) 2023.04.07 [FLUTTER] 리펙토리(Refactory) (0) 2023.04.07