每次重新打开页面时,我创建的列表视图都会重复。我在状态小部件上调用了一个方法来调用Sqflite包中的列表,但是我希望这个方法只被调用一次。我尝试使用dispose,但显然,一个方法不能被dispose(?)下面是代码的片段,谢谢
class TodoList extends StatefulWidget {
const TodoList({Key? key}) : super(key: key);
@override
State<TodoList> createState() => _TodoListState();
}
class _TodoListState extends State<TodoList> {
getAllTodos() async {
List<TodoModel> _todoList = await TodoDatabase.instance.queryAlltodos();
_todoList.forEach((todo) {
var todoModel = TodoModel(
title: todo.title,
description: todo.description,
created: todo.created,
isChecked: todo.isChecked);
context.read<TodoProvider>().todoitem.add(todoModel);
});
}
@override
void initState() {
super.initState();
getAllTodos();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
final theme = Theme.of(context);
return FutureBuilder<List<TodoModel>>(
future: TodoDatabase.instance.queryAlltodos(),
builder: (BuildContext context, AsyncSnapshot<List<TodoModel>> snapshot) {
if(!snapshot.hasData) {
return const Center(child: CircularProgressIndicator(color: Colors.amber),);
} return
Padding(
padding: const EdgeInsets.all(10),
child: Consumer<TodoProvider>(
builder: (context, value, child) => (value.newTodo.isEmpty)
? const Center(child: Text('No Todos'))
: ListView.separated(
itemCount: value.newTodo.length,
physics: const BouncingScrollPhysics(),
separatorBuilder: (context, index) => SizedBox(
height: size.height * 0.01,
),
itemBuilder: (_, i) => Slidable(
key: ValueKey(i),
startActionPane: ActionPane(
motion: StretchMotion(),
children: [
SlidableAction(
backgroundColor: Colors.green,
foregroundColor: Colors.black,
icon: Icons.edit,
label: 'Edit',
onPressed: (context) async {
TodoModel todo = value.newTodo[i];
editTodo(context, todo);
// Navigator.of(context).pushNamed(
// EditScreen.editscreen,
// arguments: todoData
// );
showSnackBar(
context, 'Edit ${todo.title}?');
},
)
],
),
endActionPane: ActionPane(
motion: ScrollMotion(),
children: [
SlidableAction(
backgroundColor: Colors.red,
foregroundColor: Colors.black,
spacing: 0,
icon: Icons.delete,
label: 'delete',
onPressed: (context) async {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(
20),
),
title:
const Text('Delete this TODO',style: TextStyle(color: Colors.amber)),
content:
const Text('Are you Sure?'),
actions: [
TextButton(
child: const Text('No',style: TextStyle(color: Colors.amber)),
onPressed: () {
Navigator.pop(context);
},
),
TextButton(
child: const Text('Yes',style: TextStyle(color: Colors.amber)),
onPressed: () async {
TodoModel todo =
value.newTodo[i];
String result =
await context
.read<
TodoProvider>()
.deleteToDo(
todo);
if (result != 'OK!') {
return showSnackBar(
context,
result);
} else {
showSnackBar(
context,
'Deleted');
Navigator.pop(
context);
}
})
]);
});
})
],
),
child: InkWell(
onTap: () {},
child: ListTile(
tileColor: theme.primaryColorLight,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
leading: Checkbox(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(3)),
value: value.newTodo[i].isChecked,
activeColor: theme.primaryColorDark,
checkColor: theme.primaryColorLight,
onChanged: (_) async {
// return setState(() { // this works too
// todo.isChecked = value;
// });
TodoModel todo = value.todoitem[i];
await context
.read<TodoProvider>()
.updateTodo(todo);
},
),
title: Text(value.newTodo[i].title),
subtitle: Text(value.newTodo[i].description),
),
),
))),
);
});
}
}
void editTodo(BuildContext context, TodoModel todo) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => EditScreen(todo: todo),
),
);
}
3条答案
按热度按时间n1bvdmb61#
在重新加载时首先清除列表。下面是一个例子
z4bn682m2#
试试这个:
11dmarpk3#
你的问题似乎在代码的内层。
我也遇到过类似的问题,数据重复。请参见以下屏幕截图:
我的问题是在提供者(Riverpod)对存储库的调用。在重建屏幕时,我一次又一次地打电话(我不确定“重建”是否是一个好的做法)。
我在使用该方法时添加了一个条件,这就解决了问题。
查看
// ADDED LINE
注解的位置。已解决:
我想你在这条线上也有类似的问题:
但这是我最好的猜测。我看不出这个方法的内在。