Flutter

[Flutter] Provider 사용하기

hminor 2023. 8. 13. 15:29

Provider 사용하기

  • 현재 상위 컴포넌트에 있는 State를 사용하고자 할 때
    • 3 Step
      • 변수 생성
      • 변수 등록
      • 변수 사용
  • Provider
    • React의 Redux 처럼 하나의 공간에 State를 보관하여 사용
    • 설치하기
// pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.4
  image_picker: ^0.8.4+4
  shared_preferences: ^2.0.11
  provider: ^6.0.1
  • 사용하기
    • State보관함(Store) 만들기 ( ChangeNotifier )
    • class Store1 extends ChangeNotifier { var name = 'kim sky'; }
    • 해당 State를 사용하고 싶은 위젯들을 전부 ChangeNotifierProvider() 위젯으로 감싸기.
      • 보통 다른 위젯들도 사용하니 최상단 MyApp을 감싸고 있는 MaterialApp을 감싸기
      • 이후 create속성이 필요하기에 return으로 Store를 넣어주고 파라미터 값도 추가.
      void main() {
        runApp(
          ChangeNotifierProvider(
            create: (c) => Store1(),
            child: MaterialApp(
              theme: style.theme,
              initialRoute: '/',
              routes: {
                '/': (c) => MyApp(),
                '/mypage': (c) => Text('마이 페이지')
              },
              // home: MyApp()
            ),
          )
        );
      }
      
    • 이후 사용시엔 context.watch<Store이름>().변수 를 통해 사용할 수 있다.
      • 근데 이상하게 모바일로 열었을 때는 에러가나는데 뭐지..?
      AppBar(title: Text(context.watch<Store1>().name),),
      
  • 이제 Store의 변수를 변경하고자 한다면
    • 객체지향언어의 특징인 캡슐화로 인해 변경하는 함수를 Store안에서 만들어주고 외부에서 해당 함수를 사용하는 형식으로 하기.
    • 사용 방법
      • context.read<Store이름>().함수명()
      • 그리고 변경 함수에는 setState를 사용하지 않고 notifyListeners()를 붙여주면 재렌더링이 된다.
      class Store1 extends ChangeNotifier {
        var name = 'kim sky';
        changeName(){
          name = 'park sky';
          notifyListeners();
        }
      }
      
      // Profile
      class Profile extends StatelessWidget {
        const Profile({super.key});
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(title: Text(context.watch<Store1>().name),),
            body: Column(
              children: [
                ElevatedButton(onPressed: (){
                  context.read<Store1>().changeName();
                }, child: Text('버튼'))
              ],
            ),
          );
        }
      }
      

숙제

인스타의 팔로우 창을 구현하기

  • follower 라는 state 구현
  • 버튼 클릭 시 +1, 한번 더 클릭 시 -1
  • 해결 방법
    • 우선 유저의 목록이 여러 개 있다는 가정하에 ListView()를 사용해서 목록을 보여주기
    • Flutter에선 map 형태, 일반적으로는 Obejct 타입의 배열을 만들어 idx를 통해 보여주기
    • 팔로잉은 팔로우면 팔로잉이 보이게, 팔로잉이면 팔로우가 보이게 하기
    class Store1 extends ChangeNotifier {
      var list = [{'name': 'kim sky', 'follow': '팔로우'}, {'name': 'park water', 'follow': '팔로우'}];
      clickFollow(idx){
        if (list[idx]['follow'] == '팔로우') {list[idx]['follow'] = '팔로잉';}
        else {list[idx]['follow'] = '팔로우';}
        notifyListeners();
      }
    }
    
    // Profile
    class Profile extends StatelessWidget {
      const Profile({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text('Instagram')
            ),
          body: ListView.builder(
            itemCount: context.watch<Store1>().list.length,
            itemBuilder: (context, idx) {
              return Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Icon(Icons.person_pin),
                  Text(context.watch<Store1>().list[idx]['name'].toString()),
                  TextButton(
                    onPressed: (){
                      context.read<Store1>().clickFollow(idx);
                    },
                    child: Text(context.watch<Store1>().list[idx]['follow'].toString())
                  ),
                ],
              );
            },
          )
        );
      }
    }