jjs815 2022. 6. 10. 22:06

context.read<> / consumer<> 의 차이점

provider의 상태를 관리하는 변수의 값이 변경되어 해당 화면을 다시 그릴 경우 consumer<>,

해당 위젯이 변경될 부분이 없으며 화면이 바뀔 내용이 없을고 하지만 provider pool(service)에 있는 요소를

1회성으로 클래스에 접근하고 싶을 때 context.read <>(); 사용

 

항상 notifyListners()를 호출하여 갱신이 된 걸 알려줘야 한다

 

[ 메인 페이지 ]

import 'package:bucket_provider/bucket_service.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(
    MultiProvider(
      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 bucketservice = BucketService()

        List<Bucket> bucketList = bucketservice.bucketList;
        return Scaffold(
          appBar: AppBar(
            title: Text("버킷 리스트"),
          ),
          body: Center(
            child: ListView.builder(
              itemCount: bucketList.length,
              itemBuilder: (context, index) {
                var bucket = bucketList[index];
                return ListTile(
                  title: Text(bucket.job),
                  trailing: IconButton(
                    icon: Icon(Icons.delete),
                    onPressed: () {
                      bucketservice.deletBucket(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 = context.read<BucketService>();
                    bucketService.createBucket(job);
                    Navigator.pop(context); // 화면을 종료합니다.
                  }
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

 

 

[ bucketservice provider]

import 'package:bucket_provider/main.dart';
import 'package:flutter/material.dart';

class BucketService extends ChangeNotifier {
  List<Bucket> bucketList = [
    Bucket('잠자기', false),
  ];

  void createBucket(String job) {
    bucketList.add(Bucket(job, false));
    notifyListeners(); //ChangeNotifier 상속을 받아서 notifyListeners() 사용가능, setstate()처럼 화면 갱신이 있다는 것을 알려줌
  }

  /// bucket 수정
  void updateBucket(Bucket bucket, int index) {
    bucketList[index] = bucket;
    notifyListeners();
  }

  void deletBucket(int index) {
    bucketList.removeAt(index);
    notifyListeners();
  }
}
반응형