[基礎知識]Providerによる状態管理の手順

Providerを使ったタスク管理アプリケーションのサンプルコード

1.ファイル構成と役割

  1. pubspec.yaml
    • 役割: アプリケーションで使用するパッケージを管理するファイル。
    • 自動生成: flutter create <project_name>コマンドを実行すると生成されます。
  2. lib/main.dart
    • 役割: アプリケーションのエントリーポイント。Providerの設定を行います。
  3. lib/models/task.dart
    • 役割: タスクモデルを定義するファイル。
  4. lib/providers/task_provider.dart
    • 役割: Providerのプロバイダを定義するファイル。
  5. lib/screens/home_screen.dart
    • 役割: タスクのリストと追加ボタンを表示するホーム画面。
  6. lib/screens/add_task_screen.dart
    • 役割: 新しいタスクを追加する画面。
  7. lib/screens/edit_task_screen.dart
    • 役割: 既存のタスクを編集する画面。
  8. lib/widgets/task_list.dart
    • 役割: タスクリストを表示するウィジェット。

2.サンプルアプリ

3.サンプルコード

以下、上記アプリのサンプルコードです。

(1)pubspec.yaml

必要なパッケージ(provider)を追加します。

Dart
name: task_management_app
description: A new Flutter project using Provider for state management.
publish_to: 'none'
version: 1.0.0+1

environment:
  sdk: ">=2.12.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  provider: ^5.0.0
  cupertino_icons: ^1.0.2

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

(2)lib/main.dart

アプリケーションのエントリーポイントを設定します。

Dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'providers/task_provider.dart';
import 'screens/home_screen.dart';

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => TaskProvider()),
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Task Management App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomeScreen(),
    );
  }
}

(3)lib/models/task.dart

タスクモデルを定義します。

Dart
class Task {
  String title;
  String description;
  bool isCompleted;

  Task({
    required this.title,
    required this.description,
    this.isCompleted = false,
  });
}

(4)lib/providers/task_provider.dart

Dart
import 'package:flutter/material.dart';
import '../models/task.dart';

// ChangeNotifierでタスクのリストを管理します
class TaskProvider with ChangeNotifier {
  List<Task> _tasks = [];

  List<Task> get tasks => _tasks;

  void addTask(Task task) {
    _tasks.add(task);
    notifyListeners();
  }

  void editTask(int index, Task task) {
    _tasks[index] = task;
    notifyListeners();
  }

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

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

(5)lib/screens/home_screen.dart

ホーム画面を作成します。

Dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/task_provider.dart';
import '../widgets/task_list.dart';
import 'add_task_screen.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Task Management'),
      ),
      body: TaskList(),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => AddTaskScreen()),
          );
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

(6)lib/screens/add_task_screen.dart

タスク追加画面を作成します。

Dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/task.dart';
import '../providers/task_provider.dart';

class AddTaskScreen extends StatelessWidget {
  final _titleController = TextEditingController();
  final _descriptionController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Add Task'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _titleController,
              decoration: InputDecoration(labelText: 'Title'),
            ),
            TextField(
              controller: _descriptionController,
              decoration: InputDecoration(labelText: 'Description'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                final title = _titleController.text;
                final description = _descriptionController.text;
                if (title.isNotEmpty && description.isNotEmpty) {
                  Provider.of<TaskProvider>(context, listen: false).addTask(
                    Task(title: title, description: description),
                  );
                  Navigator.pop(context);
                }
              },
              child: Text('Add Task'),
            ),
          ],
        ),
      ),
    );
  }
}

(7)lib/screens/edit_task_screen.dart

タスク編集画面を作成します。

Dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/task.dart';
import '../providers/task_provider.dart';

class EditTaskScreen extends StatelessWidget {
  final int index;
  final Task task;

  EditTaskScreen({required this.index, required this.task});

  final _titleController = TextEditingController();
  final _descriptionController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    _titleController.text = task.title;
    _descriptionController.text = task.description;

    return Scaffold(
      appBar: AppBar(
        title: Text('Edit Task'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _titleController,
              decoration: InputDecoration(labelText: 'Title'),
            ),
            TextField(
              controller: _descriptionController,
              decoration: InputDecoration(labelText: 'Description'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                final title = _titleController.text;
                final description = _descriptionController.text;
                if (title.isNotEmpty && description.isNotEmpty) {
                  Provider.of<TaskProvider>(context, listen: false).editTask(
                    index,
                    Task(title: title, description: description),
                  );
                  Navigator.pop(context);
                }
              },
              child: Text('Save Changes'),
            ),
          ],
        ),
      ),
    );
  }
}

(8)lib/widgets/task_list.dart

タスクリストを表示するウィジェットを作成します。

Dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/task_provider.dart';
import '../screens/edit_task_screen.dart';

class TaskList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<TaskProvider>(
      builder: (context, taskProvider, child) {
        return ListView.builder(
          itemCount: taskProvider.tasks.length,
          itemBuilder: (context, index) {
            final task = taskProvider.tasks[index];
            return ListTile(
              title: Text(task.title),
              subtitle: Text(task.description),
              trailing: Checkbox(
                value: task.isCompleted,
                onChanged: (value) {
                  taskProvider.toggleTaskCompletion(index);
                },
              ),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => EditTaskScreen(index: index, task: task),
                  ),
                );
              },
            );
          },
        );
      },
    );
  }
}

コメントを残す