# Flutter 에 Riverpod 적용해서 리팩토링 해보자

# 설정

# 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

# main.dart runApp() ProviderScope로 감싸자

runApp(
    const ProviderScope(
      child: TaskApp(),
    ),
  );
1
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

# 소스 작성

# 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

# 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

# Main 리팩토링

# import 추가

import '../providers/task_provider.dart';
import '../utils/storage_helper.dart';
1
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

# 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