플러터/화면구현

[플러터] RiverPod 상태 관리를 활용한 To-Do List 앱 만들기

JungMayo 2025. 1. 23. 18:24

1. TodoItem 클래스 (todo_item.dart)

TodoItem 클래스는 할 일 데이터를 정의한다. 각 할 일은 제목(title)과 완료 여부(isDone)를 속성으로 가진다.

// To-Do 데이터를 관리하는 모델 클래스이다.
class TodoItem {
  String title; // 할 일의 제목이다.
  bool isDone;  // 완료 여부를 나타낸다.

  // 생성자를 통해 데이터를 초기화한다.
  TodoItem({required this.title, this.isDone = false});

  // 새로운 객체를 생성하면서 일부 데이터를 변경할 수 있는 메서드다.
  TodoItem copyWith({String? title, bool? isDone}) {
    return TodoItem(
      title: title ?? this.title,
      isDone: isDone ?? this.isDone,
    );
  }
}

- copyWith toggleItem 2단계 코드로써 시작 메서드 실행되면 무조건 TodoItem 객체 리턴함
- 매개변수중에 하나만 변경하고 싶을 수도 있는데 그때 쓰면 유용하다.
- null 이라면 원래 있던 값을 넣으라는 의미인데... null 이 들어왔다는건 변화할 값이 없다는 의미로 쓰는 것

 

2. TodoListViewModel 클래스 (todo_list_view_model.dart)

TodoListViewModel 클래스는 To-Do 데이터를 관리하며 상태 변경 로직을 처리한다.

 

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_statement_v01/_mvvm/_05/models/todo_item.dart';

// Riverpod Notifier를 사용하여 창고를 생성한다.
class TodoListViewModel extends Notifier<List<TodoItem>> {
  @override
  List<TodoItem> build() {
    return []; // 초기 상태를 빈 리스트로 설정한다.
  }

  // 할 일을 추가하는 메서드다.
  void addItem(String title) {
    state = [...state, TodoItem(title: title)];
  }

  // 할 일의 완료 상태를 토글하는 메서드다.
  void toggleItem(TodoItem todo) {
    state = state
        .map((item) => item == todo ? item.copyWith(isDone: !item.isDone) : item)
        .toList();
  }
}

// Riverpod Provider로 창고를 등록한다.
final todoListViewModelProvider =
    NotifierProvider<TodoListViewModel, List<TodoItem>>(() {
  return TodoListViewModel();
});

- state 맵의 item을 돌고 List로 변환하는 형태인데 item과 매개변수인 todo의 값이 같을 때! item의 copyWith를 호출하여 그 안의 매개변수 내용을 변경시킨다. -> 그러면 나머지 내용은 그대로고 해당 isDone 값만 바뀌겠지.

3. TodoListView 위젯 (todo_list_view.dart)

TodoListView는 사용자가 할 일을 추가하고 상태를 변경할 수 있는 UI를 제공한다.

주요 기능

  • 텍스트 필드를 사용해 할 일을 입력한다.
  • "추가" 버튼을 눌러 새로운 할 일을 등록한다.
  • 체크박스를 통해 완료 상태를 변경한다.

 

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_statement_v01/_mvvm/_05/models/todo_item.dart';
import 'package:flutter_statement_v01/_mvvm/_05/view_models/todo_list_view_model.dart';

class TodoListView extends ConsumerWidget {
  TodoListView({super.key});

  // 텍스트 입력을 제어하는 컨트롤러다.
  TextEditingController _controller = TextEditingController();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // 상태를 구독하여 데이터를 가져온다.
    final todos = ref.watch(todoListViewModelProvider);
    // 상태 변경 메서드를 호출하기 위해 Notifier에 접근한다.
    final todoNotifier = ref.watch(todoListViewModelProvider.notifier);

    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.all(16.0),
          child: TextField(
            controller: _controller,
            decoration: InputDecoration(
              hintText: 'Enter todo item...',
              suffixIcon: IconButton(
                onPressed: () {
                  // 텍스트 필드의 내용을 기반으로 새로운 할 일을 추가한다.
                  todoNotifier.addItem(_controller.text);
                  _controller.clear();
                },
                icon: Icon(Icons.add),
              ),
            ),
          ),
        ),
        SizedBox(height: 16.0),
        Expanded(
          child: ListView.builder(
            itemCount: todos.length,
            itemBuilder: (context, index) {
              final TodoItem item = todos[index];
              return ListTile(
                title: Text(item.title),
                trailing: Checkbox(
                  value: item.isDone,
                  onChanged: (value) {
                    // 체크박스 클릭 시 완료 상태를 변경한다.
                    todoNotifier.toggleItem(item);
                  },
                ),
              );
            },
          ),
        ),
      ],
    );
  }
}

4. 주요 개념 정리

  1. Notifier
    • 상태를 관리하며 상태 변경 로직을 포함하는 클래스다.
    • build 메서드를 통해 초기 상태를 정의한다.
  2. NotifierProvider
    • Notifier를 사용하는 Provider로 상태 관리 기능을 제공한다.
    • ref.watch()를 통해 상태를 구독하며, ref.read()로 상태 변경 메서드를 호출할 수 있다.
  3. 불변 객체 원칙
    • 리스트나 객체를 변경할 때는 기존 데이터를 복사하여 새로운 객체로 할당해야 한다.
    • 이를 통해 상태 관리의 안정성과 예측 가능성을 보장한다.

앱의 동작

  1. 앱 실행: 앱이 실행되면 기본 상태는 빈 리스트이다.
  2. 할 일 추가: 텍스트 필드에 입력 후 "추가" 버튼을 누르면 리스트에 새로운 할 일이 추가된다.
  3. 완료 상태 변경: 리스트의 체크박스를 클릭하면 완료 여부가 토글된다.