Flutter의 UI 코드는 백엔드 코드작성를 작성하는 dart 파일 안에 같이 코드를 작성할 수 있게 되어 있습니다.
(Android Native의 UI 코드는 xml 파일에 , 백엔드 코드는 Java 또는 Kotlin 파일에 작성합니다.)
그래서 기본 프로젝트 코드를 보면 UI, 비지니스 로직 부분이 더욱 강하게 연결되어 있습니다.
그래서! Business Logic을 분리하게 도와주는 라이브러리 중 Provider 라이브러리를 활용하게 되었습니다.
(참고로, Bloc 패턴 라이브러리도 존재합니다. Provider 보다 더욱 비지니스 로직을 분리하기에는 좋지만, 학습량이 더욱 많아
대규모 프로젝트에 적합합니다. )
Provider가 무슨 역할을 하나요?
=> Provider 라이브러리는 Data Class를 생성 및 관리를 해줍니다.
즉, 사용자가 직접 Data Class를 생성하지않고, Provider 라이브러리에게 생성을 요청해야합니다.
그러면 무슨 효과가 있나요?
=> Provider 라이브러리가 Data Class의 변화를 감지하고, 사용자에게 알려줍니다. 굉장히 편하죠!
Provider의 로직이 어떻게 돌아가는지 코드로 살펴봅시다.
(작성한 예제 코드 버전은 4.0.4 입니다.)
1. ChangeNotifier 클래스 생성
원문: ChangeNotifier is a simple class included in the Flutter SDK which provides change notification to its listeners. 해석: ChangeNotifier는 Flutter SDK에 포함된 클래스로 청취자에게 변경 알림을 제공해준다. |
ChangeNotifier를 믹스인 또는 상속받습니다.
데이터를 갱신하는 코드는 notifyListener() 를 작성해주면 됩니다.
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;
set count(int value) {
_count = value;
notifyListeners();
}
void increment() {
_count++;
notifyListeners();
}
}
2. Provider 데이터 생성
원문: ChangeNotifierProvider is the widget that provides an instance of a ChangeNotifier to its descendants. 해석: ChangeNotifierProvider는 ChangeNotifier의 인스턴스를 하위 항목에 제공하는 위젯이다. |
아래의 ChangeNotifierProvider(create: (_) => Counter()) 부분을 보시면, create() 시점에 Counter 라는 ChangeNotifier를 생성합니다.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Counter()),
],
child: Consumer<Counter>(
builder: (context, counter, _) {
return MaterialApp(
supportedLocales: const [Locale('en')],
localizationsDelegates: [
DefaultMaterialLocalizations.delegate,
DefaultWidgetsLocalizations.delegate,
_ExampleLocalizationsDelegate(counter.count),
],
home: const MyHomePage(),
);
},
),
);
}
}
3. nofity 를 할 코드를 작성합니다.
위의 ChangeNotifier 클래스를 보면 increment() 코드에 notifyListener() 가 작동하고 있습니다.
class IncrementCounterButton extends StatelessWidget {
const IncrementCounterButton({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return FloatingActionButton(
onPressed: () {
Provider.of<Counter>(context, listen: false).increment(); // Notify!
},
tooltip: 'Increment',
child: const Icon(Icons.add),
);
}
}
4. 생성된 Provider 데이터에 접근
2가지 방법이 있습니다. 1) Consumer Widget을 이용 2) Provider.of 함수 사용을 하면 됩니다.
3-1) Consumer Widget : Widget Tree의 변화가 있을 경우에 사용
(아래 예제는 Widget 트리의 변화는 없지만, 그래도 사용할 수 있다.)
class CounterLabel extends StatelessWidget {
const CounterLabel({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Consumer<Counter>( // Consumer 클래스 작성
builder: (context, counter, child) => Text(counter.count.toString()),
),
],
);
}
}
3-2) Provider.of<Counter>(context) : Widget Tree의 변화가 없을 경우 사용
class CounterLabel extends StatelessWidget {
const CounterLabel({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
final counter = Provider.of<Counter>(context); // Provider.of 함수 사용
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'${counter.count}', // 데이터 적용
style: Theme.of(context).textTheme.display1,
),
],
);
}
}
<마무리>
정리하자면, 사용자는 provider 라이브러리에 데이터 클래스를 생성 요청하고, 그 데이터를 사용하는 뷰에서 구독만 해주면 됩니다.
그러면 데이터 변화에 자동으로 알림을 받을 수 있죠.
많이 사용하는 옵저버 패틴이죠.
적용 코드: https://github.com/boogil/flutter_provider/tree/master/lib
<참고 자료>
https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple
'flutter' 카테고리의 다른 글
flutter go_router vs auto_route (0) | 2024.09.11 |
---|---|
flutter thread 분석 (0) | 2024.06.05 |
How Flutter renders Widget (0) | 2019.11.23 |
Mac에 Fultter로 Android 개발하기 - 2 (0) | 2019.10.18 |
Mac에 Fultter로 Android 개발하기 - 1 (0) | 2019.10.18 |