Never give up

Flutter - Provider Selector with tuple 본문

Flutter

Flutter - Provider Selector with tuple

대기만성 개발자 2020. 12. 31. 16:53
반응형

먼저 Selector에 관한 설명은 이전 포스트를 참고해주시면 될거 같습니다

(링크 : devmemory.tistory.com/15)

 

Selector를 사용하다보면 필요한 값이 2개 이상일때가 있습니다

 

이럴 때 사용하라고 공식문서에 친절하게 Tuple을 사용하라고 나와있더군요

 

To select multiple values without having to write a class that implements ==, the easiest solution is to use a "Tuple"

(공식문서 링크: pub.dev/documentation/provider/latest/provider/Selector-class.html)

 

그래서 관련 예제를 한번 만들어봤습니다

 

메인

class SelectorExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('rebuild main');
    var items = Provider.of<SelectorData>(context, listen: false);
    return Scaffold(
        appBar: AppBar(title: Text('Selector example')),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Test1(),
            Test2(),
            Row(
                mainAxisAlignment: MainAxisAlignment.center,
                mainAxisSize: MainAxisSize.max,
                children: [
                  Container(
                      height: 80,
                      width: 100,
                      child: TextField(
                          onChanged: (value) => items.setStr1(value))),
                  Container(
                      height: 80,
                      width: 100,
                      child:
                          TextField(onChanged: (value) => items.setStr2(value)))
                ]),
            IconButton(
                icon: CircleAvatar(child: Icon(Icons.copy)),
                onPressed: () => items.setStr3()),
          ],
        ));
  }
}

Test1, 2

class Test1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Selector<SelectorData, Tuple2<String, String>>(
      selector: (context, data) => Tuple2(data.getStr2, data.getStr3),
      builder: (context, item, child) {
        print('rebuild test1');
        return Text(
            'This is str2 : ${item.item1}\nAnd this is str3 : ${item.item2}');
      },
    );
  }
}

class Test2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<SelectorData>(
      builder: (context, item, child) {
        print('rebuild test2');
        return Text('This is str1 : ${item.getStr1}');
      },
    );
  }
}

Selector Data

class SelectorData extends ChangeNotifier {
  String _str1, _str2, _str3;

  String get getStr1 => _str1;

  String get getStr2 => _str2;

  String get getStr3 => _str3;

  void setStr1(String value) {
    _str1 = value;
    notifyListeners();
  }

  void setStr2(String value) {
    _str2 = value;
    notifyListeners();
  }

  void setStr3() {
    _str3 = _str2 ?? 'N/A';
    notifyListeners();
  }
}

Textfiled의 값을 편집하면 notifyListeners가 작동하는 아주 간단한 예제입니다

 

여기서 주목할 점은 Test1에는 Selector Test2에는 Consumer를 사용했습니다

 

그리고 Selector에서 저는 값을 2개 사용할 예정이기때문에 Tuple을 사용합니다

 

Tuple을 사용하지 않는다면 builder의 item 1개밖에 사용할 수 없고

 

Selector의 두번째 제네릭값 Selector<data, DataType>의 DataType과

 

selector에서 설정하는 selector : (context, data) => data.item(변수, 콜렉션 혹은 함수 등)만 사용할 수 있습니다

 

값을 편집해보면 str1을 편집할때는 rebuild test2만 호출되고 rebuild test1은 호출이 안됩니다

 

반대로 str2을 편집하거나 버튼을 누르면 test1,2둘다 출력이 됩니다

 

Selector는 selector에서 설정한 부분이 변경되어도 notify하지 않습니다

 

하지만 Consumer는 상관없이 notify됩니다

 

간단한건 해당방법으로 쉽게 처리 가능하지만

 

collection등 복잡한 데이터를 사용하면 조금더 생각이 많이 필요할 거 같습니다

반응형
Comments