티스토리 뷰

flutter

Provider 라이브러리 사용

길 킴 2020. 2. 23. 21:50
728x90

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.
In other words, if something is a ChangeNotifier, you can subscribe to its changes.
(It is a form of Observable, for those familiar with the term.)

해석: ChangeNotifier는 Flutter SDK에 포함된 클래스로 청취자에게 변경 알림을 제공해준다. 
즉, ChangeNotifier라면 변화에 대해 구독을 할 수 있다.
(친숙한 Observable 패턴이죠잉)


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.
It comes from the 
provider package.

해석: ChangeNotifierProvider는 ChangeNotifier의 인스턴스를 하위 항목에 제공하는 위젯이다. 
그것은 Provider 라이브러리에서 제공한다. 

아래의 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

 

boogil/flutter_provider

study for mvp pattern. Contribute to boogil/flutter_provider development by creating an account on GitHub.

github.com

 

 


<참고 자료>
https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple

https://software-creator.tistory.com/26

https://pub.dev/packages/provider#-example-tab-

'flutter' 카테고리의 다른 글

How Flutter renders Widget  (0) 2019.11.23
Mac에 Fultter로 Android 개발하기 - 2  (0) 2019.10.18
Mac에 Fultter로 Android 개발하기 - 1  (0) 2019.10.18
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함