flutter pub add riverpod
위 코드로 라이브러리를 설치하면 된다.
또한 위 라이브러리는 provider를 개발한 개발자가 만든 라이브러리이며 provider보다 조금 더 편리하고 유연한 상태관리를 위한 라이브러리로 업그레이드 됐다.
이때 riverpod(다트), flutter_riverpod가 따로 있으니 반드시 flutter_riverpod로 설치해줘야한다.
이와 또 다른 유명한 라이브러리는 getX정도가 있겠고 마치 vue.js의 상태관리 라이브러리가 vuex와 pinia가 매우 유망하고 pinia로 넘어가는 시대처럼 RiverPod를 많이 쓰지만 최근에는 getX를 더 많이 사용하는 것 같다. (뇌피셜)
일단 기본적인 Riverpod를 공부하고 추후 getX를 공부하여 포스팅하겠다.
공급자라는 객체를 생성할 수 있다.
리버포드 패키지가 제공하는 클래스에 기반하여 객체를 생성하는 것이다.
이제 이 공급자는 동적 값를 제공할 수 있고 결국 그 값을 바꿀 수 있는 메서드도 제공한다.
그리고 우리 앱에서 어떤 위젯에서든 공급자에 연결된 소비자를 설정할 수 있다.
이는 리버포드 패키지가 자동으로 연결하는 것이다.
이 소비자 위젯에서 해당 공급자 값에 대한 변화를 listen할 수 있다.
혹은 공급자가 제공하는 메서드를 호출해 그러한 변화를 트리거할 수도 있다.
어떤 프레임웤이든 state를 관리하는 라이브러릴 사용할 땐 항상 app에 해당되는 부분에 warp을 하였다.
react에서는 <Provider>로 <APP>을 감싸고 vue.js에서는 app.use()로 넣어줬다. 마찬가지이다.
import 'package:riverpod/riverpod.dart';
그리고 이 공금자 객체는 반드시 최소 1개의 함수를 매개변수로 갖는다.
그리고 또 그 함수는 ProviderRef를 매개변수로 받는다. 이때 이름 그대로 변수의 타입은 ProviderRef 타입이다.
그리고 return 값은 우리가 전역 state로 사용하고 싶은 값을 return하면 된다.
앞서 사용했던 그냥 Provider는 state 값이 변하지 않을 때 사용하는 값이다. 만약 state 값이 변한다면 StateNotifierProvider객체를 사용해야한다.
그리고 이 StateNotifierProvider는 항상 StateNotifier와 함께 사용된다. 마치 StatefulWidget이 State class와 함께 사용되던 것 처럼 말이다.
그래서 StateNofifier를 상속받는 클래스는 사실 아무렇게나 이름을 지어도 되지만 전통적으로 Notifier라는 접미어는 반드시 붙어있어야한다.
그리고 StateNofifier에 들어갈 데이터 타입은 Riverpod에게 어떤 종류의 데이터가 StateNofifier에 의해 관리되고 StateNotifierProvider에 의해 최종적으로 반환되는 값이어야한다.
:
으로 initializing을 해줬다. 이때 StateNotifier에 StateNotifierProvider에서 반환할 타입을 넣주는데 이때 초기화도 마찬가지로 해당 타입에 맞춰서 초기화를 해주면 된다.StateNotifier가 갖는 데이터 타입은 앞으로 해당 state에 다룰 데이터 타입을 넣어주면 된다.
또한 StateNotifier는 기존의 컴포넌트 클래스의 생성자 함수 선언 방식과는 조금 다르기 때문에 유의깊게 살펴봐야한다.
그리고 위 사진에서는 빼먹은 것이 있는데 바로 super 메서드 내부에 초기화해주는 값에 const
키워드를 빼먹었다. 이를 추가해줘야하는 이유는 river pod로 관리되는 state값들은 mutate 되면 안 되기 때문이다. 즉, 직접적으로 수정하면 안 되고 새로운 state 객체를 생성한 후 대체해야한다.
따라서 혹시나 실수로 직접적으로 수정하려고 할 때 막아줄 수 있는 보험역할로서 const
키워드가 들어가는 것이다.
이 문장은 밑에 setFilter 메서드가 state를 설정하는 방식을 보면 쉽게 이해할 수 있다.
위 state 객체는 마치 widget과 ref와 비슷하며 StateNotifier가 제공하는 객체이다.
그리고 state객체는 StateNotifier가 들어있는 데이터 타입의 값을 갖는다.
그리고 이 state를 절대 직접 변환하면 안 된다. 오직 할당 =
연산만 가능하다.
그래서 위 코드는 state에 .contains 메서드를 사용하여 매개변수로 들어온 값이 있다면 빼고 없다면 추가해주는 메서드이다.
앞서 언급 했듯 state객체를 절대 직접변환하면 안 되기에 그래서 remove 메서드 대신 where 메서드를 사용한다.
where 메서드는 항상 새 배열을 생성한다. => 기존 데이터를 건들지 않는다.
참고로 where 메서드로 remove 함수와 같은 효과를 내는 메서드는 위 코드와 같다. where 함수는 주어진 배열에서 주어진 조건이 참인 것 만을 반환하기 때문이다.
또한 ...
spread 연산자로 기존에 값을 모두 가져오고 추가적으로 매개변수로 들어온 값을 넣어주기 위함이다.
이때 타입이 ary가 아닌 Map이라면?!
마찬가지로 spread 연산자를 하고 그 밑에 매개변수로 들어오는 값을 추가해주면 된다.
이렇게 하면 비로소 edit class가 완성 되었다. 이제 실제 Provier 클래스와 연결하면 된다.
여기 StateNotifierProvider 공급자도 마찬가지로 함수를 매개변수로 받고 그 함수의 매개변수는 ref이다.
그리고 반환 값은 당연 위에서 data를 edit 한 ~~Notifier 인스턴스가 들어와한다. 위의 Provider와 같은 원리이다. 실제 공급자가 데이터를 들고갈 데이터가 와야한다.
그리고 반환값이 있다면 반환값에 대한 type을 지정해줘야한다.
첫번째는 인스턴스의 타입이고 두번째는 인스턴스가 반환하는 데이터 타입을 넣어줘야한다.
그리고 이렇게 지정해두면 다른 consumer에서 사용했을 때 보다 나은 경험을 제공할 것이다.
그리고 실행은 .read() 메서드를 사용하여 가져온다. watch는 여기서 적절하지 않다. 메서드를 사용하는데 메서드는 객체의 메서드이고 이를 watch 주시하는 것은 메모리 낭비이기 때문에 read를 공급자를 불러들인 다음 해당 메서드를 사용하면 된다.
또한 initState와 같은 1번 실행되는 함수에서도 watch 함수를 사용할 필요가 없다. 왜? => 코드 자체가 1번만 실행되기 때문에