以下是一个使用 flutter_riverpod 的深入案例:

假设我们正在构建一个简单的待办事项应用程序。我们需要能够添加、编辑、删除和标记待办事项为已完成。我们将使用 flutter_riverpod 来管理应用程序的状态。

首先,我们需要创建一个待办事项类。它将包含待办事项的标题、描述和完成状态:

class Todo {
  String title;
  String description;
  bool isCompleted;

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

接下来,我们需要创建一个提供者来管理待办事项的状态。我们将使用 StateNotifierProvider 提供者,它将使用 StateNotifier 来管理状态:

final todosProvider = StateNotifierProvider<TodosNotifier, List<Todo>>((ref) {
  return TodosNotifier();
});

class TodosNotifier extends StateNotifier<List<Todo>> {
  TodosNotifier() : super([]);

  void addTodo(Todo todo) {
    state = [...state, todo];
  }

  void editTodo(int index, Todo todo) {
    state = [
      ...state.sublist(0, index),
      todo,
      ...state.sublist(index + 1),
    ];
  }

  void deleteTodo(int index) {
    state = [
      ...state.sublist(0, index),
      ...state.sublist(index + 1),
    ];
  }

  void toggleTodoCompletion(int index) {
    final todo = state[index];
    state = [
      ...state.sublist(0, index),
      todo.copyWith(isCompleted: !todo.isCompleted),
      ...state.sublist(index + 1),
    ];
  }
}

接下来,我们可以在我们的应用程序中使用提供者。在这个示例中,我们将创建一个简单的页面来显示待办事项列表,并提供添加、编辑和删除待办事项的功能。我们还将为每个待办事项提供一个复选框,以标记待办事项是否已完成:

class TodosPage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final todos = watch(todosProvider);

    return Scaffold(
      appBar: AppBar(
        title: const Text('Todos'),
      ),
      body: ListView.builder(
        itemCount: todos.length,
        itemBuilder: (context, index) {
          final todo = todos[index];

          return ListTile(
            leading: Checkbox(
              value: todo.isCompleted,
              onChanged: (_) {
                context.read(todosProvider.notifier).toggleTodoCompletion(index);
              },
            ),
            title: Text(todo.title),
            subtitle: Text(todo.description),
            trailing: IconButton(
              icon: const Icon(Icons.delete),
              onPressed: () {
                context.read(todosProvider.notifier).deleteTodo(index);
              },
            ),
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => TodoEditorPage(
                    todo: todo,
                    onSave: (editedTodo) {
                      context.read(todosProvider.notifier).editTodo(index, editedTodo);
                      Navigator.pop(context);
                    },
                  ),
                ),
              );
            },
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.add),
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => TodoEditorPage(
                onSave: (newTodo) {
                  context.read(todosProvider.notifier).addTodo(newTodo);
                  Navigator.pop(context);
                },
              ),
            ),
          );
        },
      ),
    );
  }
}

class TodoEditorPage extends StatefulWidget {
  final Todo? todo;
  final Function(Todo) onSave;

  const TodoEditorPage({
    Key? key,
    this.todo,
    required this.onSave,
  }) : super(key: key);

  @override
  _TodoEditorPageState createState() => _TodoEditorPageState();
}

class _TodoEditorPageState extends State<TodoEditorPage> {
  late TextEditingController _titleController;
  late TextEditingController _descriptionController;

  @override
  void initState() {
    super.initState();

    _titleController = TextEditingController(text: widget.todo?.title ?? '');
    _descriptionController = TextEditingController(text: widget.todo?.description ?? '');
  }

  @override
  void dispose() {
    _titleController.dispose();
    _descriptionController.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.todo != null ? 'Edit Todo' : 'Add Todo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            TextField(
              controller: _titleController,
              decoration: const InputDecoration(labelText: 'Title'),
            ),
            const SizedBox(height: 16),
            TextField(
              controller: _descriptionController,
              decoration: const InputDecoration(labelText: 'Description'),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: () {
                final newTodo = Todo(
                  title: _titleController.text,
                  description: _descriptionController.text,
                );

                widget.onSave(newTodo);
              },
              child: Text(widget.todo != null ? 'Save' : 'Add'),
            ),
          ],
        ),
      ),
    );
  }
}

最后,我们可以在我们的 main.dart 文件中使用 ProviderScope 来包装我们的根小部件,以确保提供者可以在整个应用程序中使用:

void main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}

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

这是一个简单的使用 flutter_riverpod 深入案例,展示了如何使用 StateNotifierProviderConsumerWidget 来管理和消费状态。通过这个案例,我们可以看到如何使用 flutter_riverpod 来构建复杂的应用程序。

Flutter Riverpod 深入使用案例:构建待办事项应用

原文地址: https://www.cveoy.top/t/topic/pgAe 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录