共享首选项中的布尔值不会反映在 UI Flutter 上

问题描述 投票:0回答:1

我正在开发一个待办事项应用程序,其中两个功能是将待办事项标记为已完成以及取消标记为已完成。它在按下时正常工作,并且

isDone
值也保存在共享首选项中,但是当我重新打开应用程序或更改屏幕时,它不会在 UI 上反映之前保存的
isDone
值。

这就是我的 todoWidget.dart 的样子:

import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:todo/model/todo.dart';
import 'package:todo/provider/todoProvider.dart';
import 'package:todo/widgets/todoEditorWidget.dart';

class TodoWidget extends StatefulWidget {
  final ToDo todo;
  const TodoWidget({super.key, required this.todo});

  @override
  State<TodoWidget> createState() => _TodoWidgetState();
}

class _TodoWidgetState extends State<TodoWidget> {

  Color _iconColor = Colors.white;
  TextDecoration _todoTextDecoration = TextDecoration.none;
  bool _editButtonVisibility = true;

  void _markAsDone() async {
    setState(() {
      widget.todo.isDone = true;
      _iconColor = Colors.green;
      _todoTextDecoration = TextDecoration.lineThrough;
      _editButtonVisibility = false;
    });

    final prefs = await SharedPreferences.getInstance();
    final isDoneKey = 'isDone_${widget.todo.id}';
    await prefs.setBool(isDoneKey, true);
  }

  void _unmarkAsDone() async {
    setState(() {
      widget.todo.isDone = false;
      _iconColor = Colors.white;
      _todoTextDecoration = TextDecoration.none;
      _editButtonVisibility = true;
    });

    final prefs = await SharedPreferences.getInstance();
    final isDoneKey = 'isDone_${widget.todo.id}';
    await prefs.setBool(isDoneKey, false);
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      color: widget.todo.backgroundColor,
      margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 6),
      child: Padding(
        padding: const EdgeInsets.fromLTRB(8, 10, 0, 10),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Expanded(
              child: Row(
                children: [
                  Text(
                    widget.todo.todoTime!,
                    style: const TextStyle(
                      fontSize: 18.0,
                    ),
                  ),
                  const SizedBox(width: 20,),
                  Expanded(
                    child: Text(
                      widget.todo.todoTask!,
                      softWrap: true,
                      style: TextStyle(
                        fontSize: 18.0,
                        decoration: _todoTextDecoration,
                      ),
                    ),
                  ),
                ],
              ),
            ),
            Row(
              children: [
                IconButton(
                  onPressed: () => widget.todo.isDone ? _unmarkAsDone() : _markAsDone(),
                  icon: Icon(Icons.done, color: _iconColor,),
                  padding: const EdgeInsets.all(5.0),
                  constraints: const BoxConstraints(),
                  tooltip: 'mark as done',
                ),
                Visibility(
                  visible: _editButtonVisibility,
                  child: IconButton(
                    onPressed: () => _editTodo(widget.todo),
                    icon: const Icon(CupertinoIcons.pencil),
                    padding: const EdgeInsets.all(5.0),
                    constraints: const BoxConstraints(),
                    tooltip: 'edit task',),
                ),
                IconButton(
                  onPressed: _deleteTodo,
                  icon: const Icon(CupertinoIcons.trash),
                  padding: const EdgeInsets.all(5.0),
                  constraints: const BoxConstraints(),
                  tooltip: 'delete task',),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

并加载值,从

LoadTodos
类调用
TodoProvider
方法:

Future<void> loadTodos() async {
    final prefs = await SharedPreferences.getInstance();
    final savedTodos = prefs.getStringList('todos');
    if (savedTodos != null) {
      todosList = savedTodos.map((jsonString) {
        final todo = ToDo.fromJson(jsonDecode(jsonString));
        final isDoneKey = 'isDone_${todo.id}';
        todo.isDone = prefs.getBool(isDoneKey) ?? false; // Load the isDone status
        return todo;
      }).toList();
    }
  }

在主页上构建待办事项

ListView
时调用。这就是我的
FutureBuilder
的样子:

FutureBuilder<void>(
                    future: Provider.of<ToDoProvider>(context).loadTodos(),
                    builder: (context, snapshot) {
                      if (snapshot.connectionState == ConnectionState.done) {
                        return Consumer<ToDoProvider>(
                          builder: (context, todoProvider, child) {
                            final todosForSelectedDate = todoProvider.getTodosForDate(selectedDate);
                            // Sort the todos list by time in ascending order
                            todosForSelectedDate.sort((a, b) {
                              final timeA = DateTime.parse('2023-10-08 ${a.todoTime}:00');
                              final timeB = DateTime.parse('2023-10-08 ${b.todoTime}:00');
                              return timeA.compareTo(timeB);
                            });
        
                            if (todosForSelectedDate.isEmpty) {
                              return Column(
                                children: [
                                  const SizedBox(height: 30,),
                                  Center(
                                    child: Text("No todos today", style: Theme.of(context).textTheme.headlineLarge?.copyWith(fontSize: 25),),
                                  ),
                                ],
                              );
                            } else {
                              return Expanded(
                                child: ListView.builder(
                                  itemCount: todosForSelectedDate.length,
                                  itemBuilder: (context, index) {
                                    return TodoWidget(todo: todosForSelectedDate[index]);
                                  },
                                  physics: const BouncingScrollPhysics(),
                                ),
                              );
                            }
                          },
                        );
                      } else if (snapshot.connectionState == ConnectionState.waiting) {
                        return const CircularProgressIndicator();
                      } else {
                        return const Center(child: Text('Error loading todos'));
                      }
                    },
                  ),

每当我重新打开应用程序或更改日期,然后返回到同一个应用程序时,标记为“完成”的待办事项就会被取消标记。我错过了什么?

flutter boolean sharedpreferences
1个回答
0
投票

您可以检查以下解决方案:

如何使用共享首选项保存布尔值

在共享首选项中存储 bool 类型变量的前缀。

© www.soinside.com 2019 - 2024. All rights reserved.