Flutter Bloc 로 Todo 어플 만들기
1. state는 atomic 하게 만들기
2. state는 별도의 클래스로
3. copyWith 함수로 항상 새로운 상태를 만들기
4. Equtable을 사용해서 해당 클래스가 서로 같은지 비교하게 하기
Todo 모델입니다.
uuid 를 만들어서 할일이 생성 될 때마다 고유의 id값을 만들어줍니다.
Filter는 지금 할일이 해야 하는 할일인지, 끝난일인지, 모든 값인지 보여줍니다.
Equtable 패키지를 이용해서 앞으로 Todo의 클래스와 이후 Cubit안에 쓰여질 클래스의 값이 일치하는지 도와줍니다.
import 'package:equatable/equatable.dart';
import 'package:uuid/uuid.dart'; // Import Equatable package
enum Filter { all, active, completed }
Uuid uuid = Uuid();
class Todo extends Equatable {
// Extend Equatable
final String id;
final String desc;
final bool completed;
Todo({String? id, required this.desc, this.completed = false})
: id = id ?? Uuid().v4(); // Ensure uuid is used directly
// Override props getter
@override
List<Object?> get props =>
[id, desc, completed]; // Ensure it returns a list of all properties
@override
String toString() => "Todo(id: $id, desc:$desc, completed: $completed)";
}
만들어야할 큐빗은 총 5개입니다.
1. todo_list -> todo 리스트
2. todo_search ->검색기능
3. todo_filter -> active, all,completed 인지
4.filtered_todo -> 검색되어진 todo
6.active_todo_counter -> 해야할 일이 얼마나 남았는지
기본 사용법은
1. 각 Cubit의 State 값을 만든다.
// ignore_for_file: public_member_api_docs, sort_constructors_first
part of 'todo_serach_cubit.dart';
class TodoSearchState extends Equatable {
final String searchItem;
TodoSearchState({
required this.searchItem,
});
//todo 검색 기능의 상태 초기 값은 ""
factory TodoSearchState.initial() {
return TodoSearchState(searchItem: "");
}
@override
List<Object> get props => [searchItem];
@override
String toString() => 'TodoSearchState(searchItem: $searchItem)';
TodoSearchState copyWith({
String? searchItem,
}) {
return TodoSearchState(
searchItem: searchItem ?? this.searchItem,
);
}
}
2. state의 상태값을 이용해서 emit(state.copyWith) 함수를 이용해서 새로운 상태값으로 변경한다.
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
part 'todo_serach_state.dart';
class TodoSerachCubit extends Cubit<TodoSearchState> {
TodoSerachCubit() : super(TodoSearchState.initial());
void setSearchTerm(String newSearchTerm) {
emit(state.copyWith(searchItem: newSearchTerm));
}
}
검색되어진 값들은 Stream으로 관리한다.
1. 필터링 되어진 Todos를 담을 변수를 만든다.
// ignore_for_file: public_member_api_docs, sort_constructors_first
part of 'filter_todos_cubit.dart';
class FilterTodosSate extends Equatable {
final List<Todo> filtredTodos;
FilterTodosSate({
required this.filtredTodos,
});
factory FilterTodosSate.initial() {
return FilterTodosSate(filtredTodos: []);
}
@override
List<Object> get props => [filtredTodos];
@override
String toString() => 'FilterTodosSate(filtredTodos: $filtredTodos)';
FilterTodosSate copyWith({
List<Todo>? filtredTodos,
}) {
return FilterTodosSate(
filtredTodos: filtredTodos ?? this.filtredTodos,
);
}
}
2.각 큐빗의 state의 상태값을 Stream으로 받아오는 변수를 선언하고, 그 값을 emit,copyWith 함수로 새로운 상태로 값을 생성한다.
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:bloc_todo/cubits/todo_filter/todo_filter_cubit.dart';
import 'package:bloc_todo/cubits/todo_list/todo_list_cubit.dart';
import 'package:bloc_todo/cubits/todo_search/todo_serach_cubit.dart';
import 'package:bloc_todo/models/todo_model.dart';
part 'filter_todos_state.dart';
class FilterTodosCubit extends Cubit<FilterTodosSate> {
late StreamSubscription todoFilterSubscription;
late StreamSubscription todoListSubscription;
late StreamSubscription todoSearchSubscription;
final TodoFilterCubit todoFilterCubit;
final TodoSerachCubit todoSerachCubit;
final TodoListCubit todoListCubit;
FilterTodosCubit({
required this.todoFilterCubit,
required this.todoSerachCubit,
required this.todoListCubit,
}) : super(FilterTodosSate.initial()) {
//해당 값이 변할 때 setFiltedTodos의 함수가 실행이 됨
todoFilterSubscription =
todoFilterCubit.stream.listen((TodoFilterState todoFilterState) {
setFilteredTodos();
});
todoListSubscription =
todoListCubit.stream.listen((TodoListState todoListState) {
setFilteredTodos();
});
todoSearchSubscription =
todoSerachCubit.stream.listen((TodoSearchState todoSearchState) {
setFilteredTodos();
});
}
//검색을 통해 필터링 되는 함수
void setFilteredTodos() {
//필터링 되는 리스트를 만든다.
List<Todo> _filteredTodos;
switch (todoFilterCubit.state.filter) {
case Filter.active:
_filteredTodos = todoListCubit.state.todos
.where((Todo todo) => !todo.completed)
.toList();
break;
case Filter.completed:
_filteredTodos = todoListCubit.state.todos
.where((Todo todo) => todo.completed)
.toList();
break;
case Filter.all:
default:
_filteredTodos = todoListCubit.state.todos;
break;
}
if (todoSerachCubit.state.searchItem.isNotEmpty) {
_filteredTodos = _filteredTodos
.where((Todo todo) => todo.desc
.toLowerCase()
.contains(todoSerachCubit.state.searchItem))
.toList();
}
//여기서 만들어진 _filteredTodos는 새로운 상태로 filteredTodos의 값이 됨
emit(state.copyWith(filtredTodos: _filteredTodos));
}
@override
Future<void> close() {
todoFilterSubscription.cancel();
todoListSubscription.cancel();
todoSearchSubscription.cancel();
return super.close();
}
}
큐빗이 많아지니까
한꺼번에 export 할 수 있는 cubits.dart 파일을 만든다.
//여기에 값
export 'todo_filter/todo_filter_cubit.dart';
export 'todo_search/todo_serach_cubit.dart';
export 'todo_list/todo_list_cubit.dart';
export 'active_todo_counter/active_todo_counter_cubit.dart';
export 'filter_todos/filter_todos_cubit.dart';
'Flutter-플러터 > 플러터 공부' 카테고리의 다른 글
Flutter 캡쳐 후 공유하기 기능 구현 (0) | 2024.04.07 |
---|---|
Flutter bloc 공부 3 - Todo 앱 (0) | 2024.03.17 |
Flutter - 가계부 월 고정 지출 반복적으로 입력 구현 (0) | 2024.03.02 |
Flutter 앱 버전 체크해서 알람 만들기 (0) | 2024.02.23 |
Flutter - supabase를 활용한 가계부 백업 기능 구현 (1) | 2024.02.20 |