我正在学习 flutter,现在正在使用 sqflite 进行本地存储的待办事项列表项目。我在用于构建我的 SliverList 的卡片 (TestListItem) 的活动中实现了一个复选框,并希望在用户关闭和重新打开应用程序时保存它的状态。我尝试使用 SharedPreferences:
class _TestListItemState extends State<TestListItem> {
bool _checkbox = false;
final TextEditingController updatedTaskController =
TextEditingController();
final TextEditingController updatedDateController =
TextEditingController();
@override
void initState() {
_loadCheckedValue();
}
_savedCheckedValue() async {
SharedPreferences prefs = await
SharedPreferences.getInstance();
setState(() {
prefs.setBool("check", _checkbox);
});
}
_loadCheckedValue() async {
SharedPreferences prefs = await
SharedPreferences.getInstance();
bool? isChecked = prefs.getBool("check");
setState(() {
_checkbox = isChecked ?? false;
});
}
这是复选框:
child: CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
secondary: IntrinsicWidth(
child: Row(...),
)
title: Text(...),
),
subtitle: Text(...),
),
activeColor: fabColor,
value: _checkbox,
onChanged: (bool? value) async {
setState(() {
_checkbox = !_checkbox;
_savedCheckedValue();
});
}),
这是提供者:
class TaskProvider extends ChangeNotifier {
List<TaskModel> tasks = [];
List<bool> checked = [];
Future insertInDatabase(String activity, String date) async {
final newTask =
TaskModel(taskId: const Uuid().v1(), activity: activity,
date: date);
tasks.add(newTask);
await TaskDao().save(TaskModel(
taskId: newTask.taskId,
activity: newTask.activity,
date: newTask.date));
notifyListeners();
}
Future<List<TaskModel>> readFromDatabase() async {
final taskList = await TaskDao().findAll();
tasks = taskList;
return tasks;
}
Future updateFromDatabase(
String taskId,
String activity,
String date,
) async {
final updatedTask =
TaskModel(taskId: taskId, activity: activity, date: date);
await TaskDao().update(updatedTask);
notifyListeners();
}
Future deleteFromDatabase(String taskId) async {
await TaskDao().delete(taskId);
notifyListeners();
}
}
这是我的 SliverList:
child: Consumer<TaskProvider>(
builder: (BuildContext context, TaskProvider provider,
Widget? child)
{return FutureBuilder<List<TaskModel>>(
future: provider.readFromDatabase(),
builder: (context, snapshot) {
var items = snapshot.data;
switch (snapshot.connectionState) {
case ConnectionState.none:
{
return const Loading();
}
case ConnectionState.waiting:
{
return const Loading();
}
case ConnectionState.active:
{
return const Loading();
}
case ConnectionState.done:
{
if (snapshot.hasData && items != null) {
if (items.isNotEmpty) {
return CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(
child: Text(...),
),
SliverPadding(...),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return TestListItem(
task: items[index], index:
index,);
},
childCount: items.length,
),
),
),
],
);
}
}
有了这个,我正在保存状态,但它对所有复选框应用相同的值(当我关闭并重新打开应用程序时,它们都被选中,反之亦然)。
我不知道我能做些什么来单独保存它们。我是否必须在提供程序中保存一个 bool 列表(代表选中的值),或者在 sqflite 数据库中创建一个列(再次代表选中的值)?
SharedPreferences 应该很简单吧?我该如何解决...
非常感谢 Yeasin Sheikh 的帮助,我设法找到了正确的代码来实现我想要的。
解决方案基于您将 taskId 作为键传递给 SharedPreferences 的答案,而在函数 _savedCheckedValue() 中我忘记更新 _checkbox 值。
工作代码如下:
class TestListItem extends StatefulWidget {
final TaskModel task;
final int index;
const TestListItem({
Key? key,
required this.task,
required this.index,
}) : super(key: key);
@override
State<TestListItem> createState() => _TestListItemState();
}
class _TestListItemState extends State<TestListItem> {
bool _checkbox = false;
@override
void initState() {
super.initState();
_loadCheckedValue();
}
_savedCheckedValue(bool isChecked) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
prefs.setBool(widget.task.taskId, isChecked);
});
}
_loadCheckedValue() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool? isChecked = prefs.getBool(widget.task.taskId);
setState(() {
_checkbox = isChecked ?? false;
});
}
在 CheckBoxListTile 的 onChanged 方法中:
onChanged: (bool? value) {
setState(() {
_checkbox = !_checkbox;
_savedCheckedValue(_checkbox);
});
}