ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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()를 호출 하는 경우 Consumerbuilder가 호출되며 자동으로 화면이 갱신

     

    • 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

     

Designed by Tistory.