[Flutter][Package] Provider

이상우·2022년 7월 4일
0
post-thumbnail

Intro

부모 커스텀 위젯에 있던걸 자식 커스텀 위젯으로 보내고 싶으면

3-step 으로 보내라고 했습니다.

근데 부모 -> 자식이 아니라 부모 -> 자식 -> 손자 위젯으로 보내고 싶으면 코드가 너무 복잡하고 길어짐.

이렇게 자식 위젯에 요소를 넘겨줄 때 코드가 길어진다면 Provider를 사용해 간단하게 요소(state OR 함수)를 관리해보자.

Provider는 전송 없이 모든 위젯이 state를 직접 가져다쓸 수 있게 만들어주는 패키지입니다.

실은 플러터 기본 기능으로 InheritedWidget 어쩌구 기능이 있긴 한데

문법이 더러워서 쉽게 바꿔주는 패키지 설치해서 쓰는 것임



1. Provider 패키지 사용하기

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.1 

.dart

import 'package:provider/provider.dart'; 



2. State를 보관하는 Store 만들기

class Store1 extends ChangeNotifier { 
  var name = 'john kim';
}



3. Store 등록하기

store를 사용할 위젯들을 전부 ChangeNotifierProvider() 로 감싸면 됩니다.

모든 위젯들이 사용할거면 MaterialApp() 을 감싸면 되겠군요.

void main() {
  runApp(
      ChangeNotifierProvider(
          create: (c) => Store1(),
          child: MaterialApp(
              theme: style.theme,
              home: MyApp()
          )
      )
  );
}
MultiProvider(
    providers: [
      ChangeNotifierProvider(create: (c) => Store1()),
      ChangeNotifierProvider(create: (c) => Store2()),
    ],
    child: MaterialApp( 어쩌구 ),
), 

ChangeNotifierProvider()

create: 아까 만들었던 store 넣기.

child: 안에는 store 적용할 위젯을 넣기.



4. store에 있던 state 사용하는 코드 context.watch<store명>()

state를 사용하고 싶으면 context.watch<store명>() 이걸 쓰면 된다.

Text(context.watch<Store1>().name) 



5. State 변경하고 싶으면 setState 아님, notifyListeners()이거 함수 안에 쓰면 됨

class Counter extends ChangeNotifier { 
  var name = 'john kim';
  changeName() {
    name = 'john park';
    notifyListeners();  
  }
}

state변경 다 한 후에 notifyListeners() 를 사용하면 state 사용중인 위젯이 자동 재렌더링이 됩니다.


6.state를 변경하고 싶으면 context.read<store명>().함수명()

ElevatedButton(
  onPressed: (){
    context.read<Store1>().changeName();
  }, 
  child: Text('팔로우')
)

state를 변경하고 싶으면 context.read<store명>().함수명() 이걸 쓰면 됩니다.

그럼 store 안에 있던 함수를 실행해줍니다.

그래서 Profile 페이지 안에 버튼 만들고 눌러봤더니 진짜 이름이 바뀌는군요.

@Provider 관련 ERROR 해결

Tried to listen to a value exposed with provider, from outside of the widget tree.

This is likely caused by an event handler (like a button's onPressed) that called
Provider.of without passing listen: false.

To fix, write:
Provider.of<Store>(context, listen: false);

It is unsupported because may pointlessly rebuild the widget associated to the
event handler, when the widget tree doesn't care about the value.

The context used was: HomePage(dependencies: [_LocalizationsScope-[GlobalKey#e3db6], _InheritedProviderScope<Store2?>], state: _HomePageState#5c9be)
'package:provider/src/provider.dart':
Failed assertion: line 274 pos 7: 'context.owner!.debugBuilding ||
listen == false ||
debugIsInInheritedProviderUpdate'

해결방안

state바뀔 때 재렌더링필요없는 곳에선 .watch 쓰면 뭐라고 합니다

.read로 바꾸면 됩니다.

profile
Flutter App Developer

0개의 댓글