일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 카프카
- DDD
- querydsl
- 스프링
- Axon framework
- 자바공부
- 스프링부트
- JPA 공부
- JPA예제
- 자료구조공부
- 플러터 공부
- 기술공부
- 코테준비
- nestjs스터디
- K8S
- 스프링부트공부
- JPA공부
- JPA
- JPA스터디
- 스프링 공부
- nestjs공부
- Flutter
- Kafka
- 프로그래머스
- 스프링공부
- 코테공부
- 기술면접공부
- 알고리즘공부
- 플러터 개발
- nestjs
- Today
- Total
DevBoi
[Flutter] Riverpod 적용기 (기본) 본문
Flutter로 Riverpod를 적용하여 개발을 진행해보자
Riverpod는 누구나 알다싶이, 상태 관리에 대한 기술이다.
상태관리란, 데이터가 변경될때, 메모리관리 또는 UI 컴포넌트 영향등을 관리해주는 기술이라고 이해하면 편하다.
야생의 개발자의 경우에는 그냥 일단 개발을 따라 해보고 천천히 이해하는데
나도 약간 이런걸 좋아하는것같다?
일단 적용해보자
1. Riverpod 플러그인 추가
flutter_riverpod: ^2.6.1
2. Riverpod 요소 State
State는 상태관리의 대상이 되는 Entity라고 이해하면 편하다.
class SensorState {
final double accX, accY, accZ;
final double gyroX, gyroY, gyroZ;
SensorState({
this.accX = 0.0,
this.accY = 0.0,
this.accZ = 0.0,
this.gyroX = 0.0,
this.gyroY = 0.0,
this.gyroZ = 0.0,
});
}
3. Riverpod 요소 Notifier
Notifier의 존재 이유는 이렇다.
상태관리에 대한 State의 값을 변경하거나, 필요한 동작들을 이 Notifier를 통해서 진행하게 된다.
class SensorNotifier extends StateNotifier<SensorState> {
SensorNotifier() : super(SensorState());
StreamSubscription<AccelerometerEvent>? _accelerometerSubscription;
StreamSubscription<GyroscopeEvent>? _gyroscopeSubscription;
bool isListening = false;
void startListening() {
if (isListening) return;
isListening = true;
_accelerometerSubscription = accelerometerEventStream().listen((event) {
state = SensorState(
accX: event.x,
accY: event.y,
accZ: event.z,
gyroX: state.gyroX,
gyroY: state.gyroY,
gyroZ: state.gyroZ,
);
});
_gyroscopeSubscription = gyroscopeEventStream().listen((event) {
state = SensorState(
accX: state.accX,
accY: state.accY,
accZ: state.accZ,
gyroX: event.x,
gyroY: event.y,
gyroZ: event.z,
);
});
}
void stopListening() {
if (!isListening) return;
isListening = false;
_accelerometerSubscription?.cancel();
_gyroscopeSubscription?.cancel();
}
@override
void dispose() {
_accelerometerSubscription?.cancel();
_gyroscopeSubscription?.cancel();
super.dispose();
}
}
4. Riverpod 요소 provider 선언
이제 ui에서 호출해서 꺼내쓸수있도록, 선언을 해준다.
개발자의 기호에 따라서 특정 파일에 모아 놓는 경우도있다
final sensorProvider = StateNotifierProvider<SensorNotifier, SensorState>((ref) {
return SensorNotifier();
});
5. Riverpod ui에 매핑
이런식으로 하면, 홈에서 해당 프로바이더를 호출하고, 해당 프로바이드의 notifier를 통해 state를 상태관리할 수있게 된다.
class HomeView extends ConsumerWidget {
StreamSubscription<AccelerometerEvent>? _accelerometerSubscription;
StreamSubscription<GyroscopeEvent>? _gyroscopeSubscription;
bool isRecording = false;
@override
Widget build(BuildContext context, WidgetRef ref) {
final sensorState = ref.watch(sensorProvider);
final sensorNotifier = ref.read(sensorProvider.notifier);
return GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: Scaffold(
body: SingleChildScrollView(
child: Container(
width: mediaQueryData.size.width,
height: mediaQueryData.size.height * 0.8,
color: Color(0xFFD6DBED),
child: Padding(
padding: EdgeInsets.only(top: 30.v,left: 40.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'항공기 상태',
style: TextStyle(
color: Color(0xFF233B6E),
fontSize: 13,
fontFamily: 'Pretendard',
fontWeight: FontWeight.w800,
),
),
SizedBox(height: 5.v),
AirplaneStatusWidget(),
SizedBox(height: 15.v,),
Text(
'통신 상태 (클라우드 서버)',
style: TextStyle(
color: Color(0xFF233B6E),
fontSize: 13,
fontFamily: 'Pretendard',
fontWeight: FontWeight.w800,
),
),
SizedBox(height: 5.v),
NetworkStatusWidget(),
SizedBox(height: 10.v),
Text(
'저장 공간',
style: TextStyle(
color: Color(0xFF233B6E),
fontSize: 13,
fontFamily: 'Pretendard',
fontWeight: FontWeight.w800,
),
),
SizedBox(height: 5.v),
StorageStatusWidget(),
SizedBox(
width: mediaQueryData.size.width * 0.8,
child: NovaChartWidget()
)
],
),
),
),
),
floatingActionButton: SpeedDial(
activeBackgroundColor: Color(0xFF233B6E),
buttonSize: Size(90, 90), // FAB 크기 키우기
childrenButtonSize: Size(90, 90), // 펼쳐지는 버튼 크기 키우기
spaceBetweenChildren: 10,
backgroundColor: Color(0xFF233B6E),
overlayColor: Colors.transparent,
animatedIcon: AnimatedIcons.menu_close,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7), // 네모난 모양을 위해 둥근 모서리 설정
),
children: [
SpeedDialChild(
child: Icon(
isRecording ? Icons.stop : Icons.play_arrow,
color: Color(0xFF233B6E),
size: 60,),
label: isRecording ? "측정 중지" : "측정 시작",
onTap: ((){
isRecording = !isRecording;
if(isRecording){
sensorNotifier.startListening();
}
else{
sensorNotifier.stopListening();
}
}),
),
SpeedDialChild(
child: Icon(Icons.cloud_upload,color: Color(0xFF233B6E),size: 60,),
label: "업로드",
onTap: ((){
}),
),
],
),
)
);
}
}
일단 이런식으로 사용하면 된다.
나는 screen - view - widget - provider의 개념을 주로 쓴다.
스크린은 다양한 view를 가질수 있고, view는 다양한 widget을 사용할 수 있다.
공통 widget이 많은 경우, 패키지를 상단으로 빼기도한다.
그리고 이 view안에서 provider를 쓰게 된다.
아래는 패키지 구조이다. 기호나 용도에 따라서 바꾸면 된다
즐코하자
'[Mobile] > [Flutter]' 카테고리의 다른 글
[Flutter] textformfield 클릭시 화면이 리스트를 가리는 현상 (0) | 2024.01.17 |
---|---|
[Flutter] StreamBuilder State redraw 이슈 (0) | 2024.01.17 |
[flutter] 앱에 광고 달기 (1) | 2023.12.30 |
[Flutter] Icon launcher 사용하기 (0) | 2023.12.19 |
[Flutter] IOS 애플 로그인, 회원탈퇴 (0) | 2023.12.16 |