[flutter] 상태 관리 - Provider

Shin·2022년 11월 16일
0

flutter

목록 보기
3/6

Provider

Provider는 플러터의 기본 위젯은 Inherited 위젯을 기반으로 한 상태 관리 패키지다
Provider는 앞서 배운 Bloc과 비슷하게 상태 공유 말고도 관심사를 불리할 수 있다는 필요성이 있다

dependencies:
  flutter:
    sdk: flutter
  provider: ^5.0.0

Provider의 주요 개념

Provider 패키지의 구성 요소는 기본적으로 상태를 생산/소비하는 영역으로 나뉜다
상태를 생산하는 영역을 Provider라고 하고, 소비하는 영역을 Consumer라고 한다

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return Provider<int>.value(
      value: 0,
      child: MaterialApp(
        home: HomeScreen(...),
      ),
    );
  }
}

상태를 생산하는 Provider는 상태의 타입과 초기값을 위처럼 선언할 수 있다
그리고 child에 있는 위젯 내부에서 상태를 사용한다
앱 전역에서 접근하도록 하고 싶다면 MaterialApp()을 child에 넣으면 된다

return Consumer<int>(
	builder: (context, data, child){
    	return Text(data.toString());
    }
)

Consumer 위젯은 builder를 통해 상태 값(data)을 받아와 위젯을 빌드한다
이렇게 안에 선언된 위젯은 상태 값이 변화할 때마다 다시 빌드되어, 가급적 상태가 필요한 부분만 선언하여 불필요한 빌드를 막아야한다

int data = Provider.of<int>(context);

위와 같이 Consumer 위젯보다 좀 더 간단한 방법도 있다


여기까지는 그저 값을 전달할 뿐 실제로 상태의 변화를 다룰 수 없다
상태의 변화를 다루기 위해 ChangeNotifier와 ChangeNotifireProvider를 사용할 수 있다

ChangeNotifire는 변화를 알려주는 역할의 객체다
따라서 객체를 ChangeNotifire를 활용해 만들면 해당 객체 값의 변화를 감지 할 수 있다
이렇게 변화를 지속적으로 감시해 변화를 알 수 있는 것을 구독이라고 표현한다

class Counter{
	int counter;
    Counter(this.count);
    
    void increment(){
    	count += 1;
    }
    
    void decrement(){
    	count -= 1;
    }
}

int 타입의 Counter라는 클래스 형태로 만든 것이다
이렇게 작성하면 Counter의 count 값의 변화를 실시간으로 받아올 수 없다
이를 위해 ChangeNotifire를 사용한다

class Counter extends ChangeNotifire{
	int counter;
    Counter(this.count);
    
    void increment(){
    	count += 1;
        notifyListeners();
    }
    
    void decrement(){
    	count -= 1;
        notifyListeners();
    }
}

ChangeNotifire를 Counter 클래스에 상속하면 위처럼 변화를 구독할 수 있는 객체가 되어 notifyListeners()를 사용할 수 있게 된다
notifyListeners()를 통해 Counter의 값이 변화했음을 알려준다

이렇게 작성된 상태를 사용할 수 있는 위젯이 바로 ChangeNotifireProvider이다
ChangeNotifire가 추가되어 단순히 데이터를 제공해주던 Provider가 상태의 변화를 다룰 수 있게 된 것이다

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => Counter(),
      child: MaterialApp(...),
    );
  }
}

여기서 문제는 MaterialApp을 ChangeNotifireProvider 하나로만 감싸면 상태를 하나밖에 다루지 못한다
이룰 위해 Provider 패키지에서는 여러 개의 Provider를 사용할 수 있는 MultiProvider를 지원한다

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => State1()),
        Provider(create: (context) => State2()),
      ],
      child: MaterialApp(...),
    );
  }
}

요약

  1. Provider : 말 그대로 "제공"해주는 역할, 상위 위젯에서 선언한 객체를 그대로 하위 위젯에서 사용할 수 있도록 제공한다
  2. Consumer : 하위 위젯에서 객체를 받아와 "사용"하는 역할, Cousumer 위젯보다는 Provider.of(context)의 형태로 많이 사용한다
  3. ChangeNotifire : 특정 클래스가 변화할 수 있는 값을 포함할 때 상속받아야 하는 클래스, 값이 변화했음을 notifyListeners()로 알려줄 수 있다
  4. ChangeNotifireProvider : ChangeNotifire를 상속한 클래스로 만들어진 객체를 "제공"해주는 Provider

출처 : 쉽고 빠른 플러터 앱 개발

0개의 댓글