본문 바로가기
관리자

Programming-[CrossPlatform]/Flutter

[제철음식 알리미] ValueListenableBuilder, ValueNotifier

728x90
반응형

제철음식 알리미 앱을 제작하며 학습했던 내용들을 정리한다.

 


 

1. ValueNotifier

제철음식 알리미는 아래와 같이 MonthSlider와 PageView로 구성되어있다. 여기서 아래 애니메이션과 같이, 두 개의 다른 요소가 서로 상호작용하며 바뀌는 월 정보를 추적해야한다. PageView를 좌우로 스와이프해도 MonthSlider의 월 정보가 바뀌어야하고, MonthSlider의 화살표를 누르더라도 PageView의 내용이 변경되어야한다.

 

 

이를 위해 현재 선택된 month 정보를 selectedMonth라는 변수로 두고 ValueNotifier로 등록했다.

 

class _HomeViewState extends State<HomeView> {
  final ValueNotifier<int> selectedMonth =
      ValueNotifier<int>(DateTime.now().month);
      
      //...중략
      
      
      
      Widget _buildHomeContent() {
    return Stack(children: [
      Builder(builder: (context) {
        return Container(
          padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
          child: Column(
            children: [
              Expanded(
                  flex: 1,
                  child: MonthSlider(
                    selectedMonth: selectedMonth,
                  )), // Month Slider
              Expanded(
                flex: 1,
                child: Align(
                  alignment: Alignment.topCenter,
                  child: _buildCategoryDropdown(),
                ),
              ),
              Expanded(
                  flex: 12,
                  child: ValueListenableBuilder<int>(
                      valueListenable: selectedMonth,
                      builder: (context, month, _) {
                        return FoodListView(
                          selectedMonth: selectedMonth,
                          selectedCategory: selectedCategory,
                        );
                      })),
            ],
          ),
        );
      }),
      Positioned(bottom: 0, left: 0, right: 0, child: AdvertisementView())
    ]);
    
    
    //... 생략
    }

 

 

2. ValueListenableBuilder

 

같은 ValueNotifier를 받는데, MonthSlider는 단순히 selectedMonth를 전달받고, FoodListView는 ValueListenableBuilder를 통

해 다소 복잡하게 정의되었다. 이것은 MonthSlider에서의 selectedMonth 변경 값은 HomeView에서 정말 selectedMonth 값만 텍스트로 보여주면 되는 반면, FoodListView는 내부에서의 selectedMonth 값의 변경이 음식 목록의 UI를 변경해야 하기 때문이다. 둘 다 내부 객체에서 selectedMonth의 변경 사항을 추적하고 부모인 HomeView로 올려주지만, UI의 변경이 필요한 FoodListView는 ValueListenableBuilder를 적용한 것이다.

 

 

 

3. dispose

 

추가로, dispose 메서드에서 selectedMonth 값을 정리해준다. 

@override
void dispose() {
  selectedMonth.dispose();
  super.dispose();
}

 

 

이는 StatefulWidget에서 ValueNotifier와 같은 리스너가 위젯이 파괴될 때도 정리되지 않는다면 메모리 누수가 발생할 수 있기 때문이다. 따라서 위젯이 파괴될 때 호출되는 dispose 메서드에 selectedMonth를 정리하는 dispose() 메서드를 호출한다. 이외에도 StreamController, AnimationController와 같은 객체들을 사용할 때는 dispose로 항상 정리해줘야 메모리 누수가 발생하지 않는다.

728x90
반응형