티스토리 뷰

Provider

 

Provieder를 쓰는 이유

 

1. 코드역할 분리

 

UI를 담당하는 코드, 네트워크를 담당하는 코드, 데이터를 담당하는 코드 등

코드를 역할에 따라 나눌 수 있다.

 

한 클래스가 여러 역할을 할수록, 클래스가 커지고 관리가 어렵게 됩니다.

따라서 클래스가 하나의 역할만 갖도록, 클래스를 나눈다.

 

2. 데이터 공유

 

하나의 데이터를 여러 페이지에서 공유해야 될 때가 있다.

그런데 페이지마다 데이터를 새로 불러온다면 앱이 복잡해지고, 비용도 많이 들 것이다.

 

이럴 때 Provider 패턴을 쓰면 데이터 공유를 쉽게 할 수 있다.

 

3. 간결한 코드

 

Provider 패턴을 쓰면 Bloc패턴에 비해

좀 더 적은 코드로 클래스들을 구분해서 쓸 수 있다.

 

 

패키지 추가

provider: ^6.0.5

 

예제(TodoList)

 

provider 부분

class Task {
  final String title;
  bool isCompleted;

  Task(this.title, this.isCompleted);
}

 

Task 클래스를 정의 해준다.

 

title: 할 일의 제목을 나타내는 문자열

isCompleted: 할 일 확인 여부를 나타내는 bool형 값

 

두 변수의 생성자를 초기화해준다.

 

 

class TaskList with ChangeNotifier {
  final List<Task> _tasks = [];

  List<Task> get tasks => _tasks;

  void addTask(String title) {
    _tasks.add(Task(title, false));
    notifyListeners();
  }

  void toggleTask(int index) {
    _tasks[index].isCompleted = !_tasks[index].isCompleted;
    notifyListeners();
  }

  void removeTask(int index) {
    _tasks.removeAt(index);
    notifyListeners();
  }
}

 

final List<Task> _tasks = []; 로 

Task클래스를 이용해 리스트 타입의 할 일 목록 변수를 선언한다.

  List<Task> get tasks => _tasks; 로

_tasks라는 프라이빗 변수를 다른 클래스에서도 쓸 수 있게 한다. 

 

ChangeNotifier 클래스 내에서 상태를 변경하고,

변경 사항을 notifyListeners()를 호출하여 provider에 알린다.

이로써 UI를 업데이트하고 상태를 반영한다.

 

 

의존성 주입

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => TaskList(),
      child: const MaterialApp(
        title: 'Todo List',
        home: TaskListScreen(),
      ),
    );
  }
}

 

ChangeNotifierProvider를 사용하여 앱의 다양한 부분에서 동일한 할 일 목록 데이터를 주입하고 공유합니다.

 

 

감시자(Listener) 등록

class TaskListScreen extends StatelessWidget {
  const TaskListScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final taskList = Provider.of<TaskList>(context); // Listener

 

Provider.of<TaskList>(context)를 사용하여

TaskList 클래스의 인스턴스인 taskList를 가져온다.

 

taskList 객체는 TaskList 클래스의 상태를 감시하고,

상태가 변경될 때마다 해당 위젯을 다시 렌더링 하도록 강제한다.

 

 

provider 활용

return Scaffold(
      appBar: AppBar(
        title: const Text('Todo List'),
      ),
      body: ListView.builder(
        itemCount: taskList.tasks.length,
        itemBuilder: (context, index) {
          final task = taskList.tasks[index];
          return ListTile(
            title: Text(task.title),
            leading: Checkbox(
              value: task.isCompleted,
              onChanged: (_) => taskList.toggleTask(index),
            ),
            trailing: IconButton(
              icon: const Icon(Icons.delete),
              onPressed: () => taskList.removeTask(index),
            ),
          );
        },
      ),

 

이 부분의 코드는 TaskListScreen 위젯이 화면에 나타나면

할 일 목록을 동적으로 생성하여 보여주는 역할을 합니다.

 

provider에서 정의한 함수들과 변수를 활용한다.

 

 

floatingActionButton: FloatingActionButton(
        onPressed: () {
          showDialog(
            context: context,
            builder: (context) {
              final TextEditingController controller = TextEditingController();
              return AlertDialog(
                title: const Text('Add Task'),
                content: TextField(
                  controller: controller,
                  decoration: const InputDecoration(hintText: 'Task Name'),
                ),
                actions: <Widget>[
                  TextButton(
                    child: const Text('Cancel'),
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                  ),
                  TextButton(
                    child: const Text('Add'),
                    onPressed: () {
                      taskList.addTask(controller.text);
                      Navigator.of(context).pop();
                    },
                  ),
                ],
              );
            },
          );
        },
        child: const Icon(Icons.add),
      ),

 

이 부분은 task를 추가하는 부분이다.

마찬가지로 provider를 활용해 구현했다.

 

 

BuildContext 활용

// context를 사용하여 할 일 목록 데이터를 가져옴
final taskList = Provider.of<TaskList>(context); 


showDialog(
  context: context, // context를 사용하여 다이얼로그를 띄움
  builder: (context) {}

 

할 일 목록 데이터를 가져올 때와 다이얼로그를 띄울 때

context가 사용되었다.

 

BuildContext를 활용하여 현재 위젯의 위치와 정보를 알 수 있으며,

상태 관리와 UI 빌드에 사용됩니다. 

 

 

MultiProvider

 

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class User extends ChangeNotifier {
  final String name;
  User(this.name);
}

class Settings extends ChangeNotifier {
  final bool darkMode;
  Settings(this.darkMode);
}

 

Provider가 여러 개 일 땐 MultiProvider를 쓴다.

 

 

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<User>(create: (_) => User('John')),
        ChangeNotifierProvider<Settings>(create: (_) => Settings(false)),
      ],
      child: const MaterialApp(
        home: HomeScreen(),
      ),
    );
  }
}

 

MultiProvider의 providers 속성에 원하는 프로바이더를 적어주면 된다.

 

providers: [
  ChangeNotifierProvider<User>(create: (_) => User('John')),
  ChangeNotifierProvider<User>(create: (_) => User('James')), // 이 값 가져옴
],

 

같은 제네릭 타입이나 자료형을 가질 경우엔 가장 밑의 값을 가져온다.

 

 

final user = Provider.of<User>(context);
final settings = Provider.of<Settings>(context);

 

Provider.of<클래스>(context)를 이용해 해당 클래스의 인스턴스를 가져올 수 있다. 

 


 

함수 재구성

 

void deleteTodo(int id) {
  dummyTodos.removeWhere((todo) => todo.id == id);
}

 

'removeWhere' 메서드를 사용해 id가 일치하는 todo를 제거한다.

 

 

void updateTodo(Todo updatedTodo) {
  final index = dummyTodos.indexWhere((todo) => todo.id == updatedTodo.id);
  if (index != -1) {
    dummyTodos[index] = updatedTodo;
  }
}

 

'removeWhere' 메소드를 사용해 id가 일치하는 todo를 수정한다.

id가 일치하는 todo가 없다면 index의 값은 -1이 된다.

 

'무스마' 카테고리의 다른 글

무스마 현장실습 종료  (0) 2023.12.31
네 번째 과제  (0) 2023.08.21
세 번째 과제  (0) 2023.08.13
두 번째 과제  (0) 2023.08.07
첫 번째 과제  (0) 2023.07.31
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함