기초 사용법을 익히기 위해 Provider를 통한 + , - 카운터 앱 예제를 만들어보도록 하겠습니다.
Bloc를 사용한 예제는 아래 링크를 통해 확인 가능합니다.
https://velog.io/@heemm/Flutter-Bloc-예제
dependencies:
flutter:
sdk: flutter
provider:
우선, provider 패키지를 프로젝트에 추가하기 위해 pubspec.yaml
파일에 위와 같은 코드를 추가하고 패키지를 가져옵니다.
import 'package:flutter/material.dart';
class CountProvider with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // 값 증가 후 상태 변경 알림
}
void decrement() {
_count--;
notifyListeners(); // 값 감소 후 상태 변경 알림
}
}
decrement();
CountProvider
내에서 상태의 count 값이 감소시키고 UI 변경을 알립니다.
increment();
CountProvider
내에서 상태의 count 값이 증가시키고 UI 변경을 알립니다.
notifyListeners()
상태가 변경된 것을 구독하고 있는 위젯들에게 알리는 역할을 합니다.
해당 메서드를 호출하지 않는다면 Provider는 상태가 변경되더라도 UI가 리로드 되지 않습니다.
class ProviderScreen extends StatelessWidget {
const ProviderScreen({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (BuildContext context) => CountProvider(), // 정의한 Provider
lazy: true, // true의 경우 기본값, 해당 예제는 설명을 위해 정의되었습니다.
child: const ScaffoldLayout(
child: ProviderLayout(),
),
);
}
}
ChangeNotifierProvider
위젯 트리에 ChangeNotifier
를 제공하고, 하위 위젯들이 해당 상태를 사용할 수 있도록 해주며, 변경된 상태를 감지하고 이때 위젯을 다시 그리는 Widget입니다.
create (필수)
상태 관리 클래스의 인스턴스를 생성함과 동시에 위젯 트리에 새로운 ChangeNotifier
를 제공해 주는 함수로, 필수 매개변수 입니다.
lazy
해당 설정은 create의 ****지정된 ****상태 클래스를 위젯 트리가 처음 빌드 될 때 바로 생성할지 혹은 필요시에 생성할지 설정하는 매개변수입니다.
기본 설정은 true
이며 이는 실제 필요한 경우에만 생성하여 앱의 리소스를 절약할 수 있습니다.
false
설정 시 위젯 트리가 처음 빌드 될 때 상태 클래스가 생성되며, 필요에 따라 초기 상태 설정이 가능합니다.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:velog_exercise/presentation/feat/provider/provider/count_provider.dart';
class ProviderLayout extends StatelessWidget {
const ProviderLayout({super.key});
@override
Widget build(BuildContext context) {
final counter = Provider.of<CountProvider>(context);
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'${counter.count}',
style: const TextStyle(fontSize: 50),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
heroTag: 'provider_decrement',
onPressed: () {
counter.decrement();
},
child: const Icon(Icons.remove),
),
FloatingActionButton(
heroTag: 'provider_increment',
onPressed: () {
counter.increment();
},
child: const Icon(Icons.add),
),
],
)
],
);
}
}
counter.count
상태 클래스의 count 값을 가져와 사용합니다.
counter.decrement();
상태 클래스의 count 감소 메서드 호출합니다.
counter.increment();
상태 클래스의 count 증가 메서드 호출합니다.
Provider 패키지에서 제공되는 Provider.of
메서드를 사용하여 상태 클래스인 CountProvider
를 현재 context
에서 가져오는 역할을 합니다.
이를 통해 가져온 상태 클래스의 데이터나 메서드에 접근 가능하며, 위젯에서 상태 변경이나 값을 불러오는 등의 작업이 가능합니다.
ChangeNotifierProvider를 통해 먼저 ChangeNotifier
를 제공받아야만 하기 때문입니다.
final counter = Provider.of<CountProvider>(context);
위 코드와 같이 context를 통해 위젯 트리 속 상태 관리 클래스의 인스턴스를 찾아 구독을 하게 되는데
이를 아래과 같이 진행하게 된다면 상태 관리 클래스가 생성되기도 전에 구독을 시도하기에 에러가 발생합니다.
즉, 존재하지 않는 것에 대한 방황을 하게 된다고 볼 수 있습니다.
class ProviderScreen extends StatelessWidget {
const ProviderScreen({super.key});
@override
Widget build(BuildContext context) {
final counter = Provider.of<CountProvider>(context);
return ChangeNotifierProvider(
create: (BuildContext context) => CountProvider(),
child: const ScaffoldLayout(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'${counter.count}',
style: const TextStyle(fontSize: 50),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
heroTag: 'provider_decrement',
onPressed: () {
counter.decrement();
},
child: const Icon(Icons.remove),
),
FloatingActionButton(
heroTag: 'provider_increment',
onPressed: () {
counter.increment();
},
child: const Icon(Icons.add),
),
],
)
],
)
),
);
}
}
에러 발생 코드를 제외한 해당 코드들의 전문은 Github 레파지토리에서 확인 가능합니다!
공식 문서
하위 링크를 통해 더욱 다양한 예제와 위젯을 볼 수 있으니 참고하시면 좋을 듯 합니다!