# Flutter 에 Riverpod 적용해서 리팩토링 해보자
- Riverpod : Flutter에서 상태 관리(State Management)를 위한 라이브러리
- https://riverpod.dev/ko/docs/introduction/getting_started (opens new window)
# 설정
# pubspec.yaml
dependency 추가
dependencies:
flutter:
sdk: flutter
shared_preferences: ^2.0.8
flutter_secure_storage: ^5.0.2
dio: ^5.0.0
flutter_riverpod: ^2.0.0
go_router: ^6.0.0
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# main.dart
runApp() ProviderScope로 감싸자
runApp(
const ProviderScope(
child: TaskApp(),
),
);
1
2
3
4
5
2
3
4
5
# 폴더 구조 분리 해주자
챗 지피티의 추천대로 고
|__config
|__config.dart
|__models
|__task.dart
|__providers
|__task_provider.dart
|__screens
|__create_screen.dart
|__done_screen.dart
|__login_screen.dart
|__main_screen.dart
|__search_screen.dart
|__services
|__task_service.dart
|__utils
|__storage_helper.dart
|__widgets
|__bottom_nav_bar.dart
main.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 소스 작성
# service 작성
class TaskService {
final Dio _dio = Dio();
static const _baseUrl =
'https://il3yh0ax0h.execute-api.ap-northeast-2.amazonaws.com/dev/api/v1';
Future<List<dynamic>> fetchTasks(String token, String done) async {
try {
final queryParameters = done == 'A' ? null : {'done': done};
final response = await _dio.get(
'$_baseUrl/todos',
queryParameters: queryParameters,
options: Options(headers: {'Authorization': token}),
);
return response.data['data']['todos'];
} catch (e) {
throw Exception('Failed to fetch tasks: $e');
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# provider 작성
class TaskNotifier extends StateNotifier<List<Task>> {
final TaskService _taskService;
TaskNotifier(this._taskService) : super([]);
Future<void> loadTasks(String token, String done) async {
try {
print('TaskNotifier loadTasks');
final tasksData = await _taskService.fetchTasks(token, done);
state = tasksData.map((data) => Task.fromJson(data)).toList();
} catch (e) {
print('Error loading tasks: $e');
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Main 리팩토링
# import 추가
import '../providers/task_provider.dart';
import '../utils/storage_helper.dart';
1
2
2
# ConsumerStatefulWidget 상속받는다
class MainScreen extends ConsumerStatefulWidget {
const MainScreen({super.key});
ConsumerState createState() => _MainScreenState();
}
class _MainScreenState extends ConsumerState<MainScreen> {
String userName = "";
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
final token = await StorageHelper.getToken();
// Token 가져와서 loadTasks 호출
ref.read(taskProvider.notifier).loadTasks(token!, 'N');
_initializeUser();
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# build 에 상태변경 감지 연결
Widget build(BuildContext context, WidgetRef ref) {
final tasks = ref.watch(taskProvider); // 상태변경 감지
.
.
.
return TaskItem(
task: tasks[index],
onCheck: () async {
final token = await StorageHelper.getToken();
if (token != null) {
// 상태 업데이트를 인라인으로 처리
ref.read(taskProvider.notifier).updateTask(token,
task.copyWith(isChecked: !task.isChecked), 'Todo');
} else {
print('Error: Token is null');
}
},
.
.
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21