본문 바로가기

Flutter/10 app Todo with provider

[Flutter] App Todo(with Provider) - 4단계 검색

오늘은 검색 기능을 구현해보자. 검색기능은 필터 기능과 and 조건으로 동작한다.

개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 2.10.3

소스코드 위치 - 05_doto_Search · mike-bskim/todo_test (github.com)

 

Release 05_doto_Search · mike-bskim/todo_test

 

github.com

 

todo_search.dart 생성 - 검색할 단어를 provider 로 구현

 

import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart';

class TodoSearchState extends Equatable {
  final String searchTerm;
  const TodoSearchState({
    required this.searchTerm,
  });

  factory TodoSearchState.init() {
    return const TodoSearchState(searchTerm: '');
  }

  @override
  List<Object> get props => [searchTerm];

  @override
  String toString() => 'TodoSearchState(searchTerm: $searchTerm)';

  TodoSearchState copyWith({
    String? searchTerm,
  }) {
    return TodoSearchState(
      searchTerm: searchTerm ?? this.searchTerm,
    );
  }
}

class TodoSearch with ChangeNotifier {
  TodoSearchState _state = TodoSearchState.init();
  TodoSearchState get state => _state;

  void setSearchTerm(String newSearchTerm) {
    _state = _state.copyWith(searchTerm: newSearchTerm);
    notifyListeners();
  }
}

 

main.dart 수정 - provider(TodoSearch) 추가 및  provider(filteredTodos.update) 수정

 

return MultiProvider(
  providers: [
    ChangeNotifierProvider<TodoList>(create: (context) => TodoList(),),
    ChangeNotifierProvider<TodoFilter>(create: (context) => TodoFilter(),),
    ChangeNotifierProvider<TodoSearch>(create: (context) => TodoSearch(),),
    ChangeNotifierProxyProvider3<TodoFilter, TodoSearch, TodoList,
        FilteredTodos>(
      create: (context) => FilteredTodos(),
      update: (
        BuildContext context,
        TodoFilter todoFilter,
        TodoSearch todoSearch,
        TodoList todoList,
        FilteredTodos? filteredTodos,
      ) =>
          filteredTodos!..update(todoFilter, todoSearch, todoList),
    ),
  ],
  child: MaterialApp(
    title: 'TODOS',
    debugShowCheckedModeBanner: false,
    theme: ThemeData(
      primarySwatch: Colors.blue,
    ),
    home: const TodosScreen(),
  ),
);

 

filtered_todos.dart 수정 - update 로직변경

 

class FilteredTodos with ChangeNotifier {
  FilteredTodosState _state = FilteredTodosState.initial();
  FilteredTodosState get state => _state;

  void update(
    TodoFilter todoFilter,
    TodoSearch todoSearch, // 인자추가
    TodoList todoList,
  ) {
    List<Todo> _filteredTodos;

    // 핵심 부분. 필터의 조건에 맞는 리스트를 만드는 기능
    switch (todoFilter.state.filter) {
      case Filter.active:
        _filteredTodos =
            todoList.state.todos.where((Todo todo) => !todo.completed).toList();
        break;
      case Filter.completed:
        _filteredTodos =
            todoList.state.todos.where((Todo todo) => todo.completed).toList();
        break;
      case Filter.all:
      default:
        _filteredTodos = todoList.state.todos;
        break;
    }
    // 로직 추가
    if (todoSearch.state.searchTerm.isNotEmpty) {
      _filteredTodos = _filteredTodos
          .where((Todo todo) =>
              todo.desc.toLowerCase().contains(todoSearch.state.searchTerm))
          .toList();
    }

    _state = _state.copyWith(filteredTodos: _filteredTodos);
    notifyListeners();
  }
}

 

providers.dart 수정 

 

export 'todo_list.dart';
export 'todo_filter.dart';
export 'filtered_todos.dart';
export 'todo_search.dart'; // 추가

 

todos_screen.dart 수정 - SearchAndFilterTodo 의 build 기능추가

 

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextFormField(
          decoration: const InputDecoration(
            labelText: 'Search todos',
            border: InputBorder.none,
            filled: true,
            prefixIcon: Icon(Icons.search),
          ),
          onChanged: (String? newSearchTerm) {
            debugPrint('Search todos: $newSearchTerm');
            if (newSearchTerm != null) {
              // 기능추가
              context.read<TodoSearch>().setSearchTerm(newSearchTerm);
            }
          },
        ),
        const SizedBox(height: 10.0),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            filterButton(context, Filter.all),
            filterButton(context, Filter.active),
            filterButton(context, Filter.completed),
          ],
        ),
      ],
    );
  }

 

 

 

 

[참고자료] udemy - Flutter Provider Essential 코스 (Korean)