android-studio - Flutter SQFlite:使用数据库内容更新列表视图时遇到问题
问题描述
我确实设法让数据库内容通过列表视图显示。但是,它没有正确执行。一旦我运行模拟器,存储在数据库中的内容应该会出现,但它们不会出现。它还表明数据库是空的,即使它显然不是。但是一旦我向数据库中添加一个新项目并单击保存,所有内容都会显示(除了我上次添加的项目,它会在下一次更新时显示)。我不知道如何解决这个问题,我尝试将 _listTodos() 放在任何地方以查看它是否在小部件之前执行,但没有任何改进。我认为问题出在 ListDisplay 类中,因此您可以跳过其余部分,为了方便起见,我只保留了整个代码。
import 'package:flutter/material.dart';
import 'model/todo_model.dart';
import 'model/todo.dart';
class ListGradesPage extends StatefulWidget {
final String title;
ListGradesPage({this.title, Key key}) : super(key: key);
_ListGradesPageState createState() => _ListGradesPageState();
}
var _todoItem;
var _lastInsertedId = 0;
final _model = TodoModel();
Future<void> _deleteTodo() async {
_model.deleteAllTodo();
}
class _ListGradesPageState extends State<ListGradesPage> {
//final _model = TodoModel();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
IconButton(
icon: Icon(Icons.edit),
onPressed: () {
print('editing...');
//_listTodos();
}),
IconButton(
icon: Icon(Icons.delete),
onPressed: () {
print('deleting all...');
setState(() {
_deleteTodo();
});
}),
],
),
body: ListDisplayPage(),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddGrade()),
);
},
child: Icon(Icons.add),
backgroundColor: Colors.blue,
),
);
}
}
class ListDisplayPage extends StatefulWidget {
ListDisplay createState() => ListDisplay();
}
class ListDisplay extends State<ListDisplayPage> {
int _selectedIndex;
List<Todo> todos = new List<Todo>();
Future<void> _listTodos() async {
todos = await _model.getAllTodos();
if (todos.isEmpty) {
print('it is empty-2.');
} else {
print("not empty-2");
}
print('To Dos:');
for (Todo todo in todos) {
print(todo);
}
}
_onSelected(int index) {
_selectedIndex = index;
}
@override
void initState() {
super.initState();
_listTodos();
// _listTodos() is not calling the function above for some reason, but executes everything below it
// In the database there are items stored however it says the databse is empty...
// until i add a new item and everything shows up except the item i recently added
if (todos.isEmpty) {
print('To Dos:');
for (Todo todo in todos) {
print(todo);
}
print('it is empty.');
} else {
print("not empty");
}
}
@override
Widget build(BuildContext context) {
//Color clr = Colors.transparent;
return todos.isEmpty
? Center(
child: Text(
'Nothing to show! Is it empty? ' + (todos.isEmpty).toString()))
: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return Card(
// <-- Card widget
child: Container(
color: _selectedIndex != null && _selectedIndex == index
? Colors.lightBlueAccent
: Colors.transparent,
child: ListTile(
leading: GestureDetector(
onTap: () {
setState(() {
_onSelected(index);
print(index);
});
},
child: Container(
width: MediaQuery.of(context).size.width / 2,
child:
Text(todos[index].sid + '\n' + todos[index].grade),
),
),
),
),
);
},
);
}
}
class AddGrade extends StatelessWidget {
String _sid, _grade;
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add Grade"),
),
body: Form(
key: _formKey,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(15.0),
child: TextFormField(
decoration: const InputDecoration(
hintText: 'Student ID',
labelText: 'SID',
),
onSaved: (String value) {
print('Saving SID $value');
_sid = value.toString();
},
),
),
Padding(
padding: const EdgeInsets.all(15.0),
child: TextFormField(
decoration: const InputDecoration(
hintText: 'Student Grade',
labelText: 'Grade',
),
onSaved: (String value) {
print('Saving Grade $value');
_grade = value.toString();
},
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_formKey.currentState.save();
_addTodo();
//_listTodos();
Navigator.pop(context);
},
child: Icon(Icons.save),
backgroundColor: Colors.blue,
),
);
}
Future<void> _addTodo() async {
Todo newTodo = Todo(sid: _sid, grade: _grade);
_lastInsertedId = await _model.insertTodo(newTodo);
}
}
控制台输出(执行时):
Restarted application in 1,607ms.
I/flutter (14196): To Dos:
I/flutter (14196): it is empty.
I/flutter (14196): not empty-2
I/flutter (14196): To Dos:
I/flutter (14196): Todo{id: 1, sid: q, grade: qq}
I/flutter (14196): Todo{id: 2, sid: w, grade: ww}
I/flutter (14196): Todo{id: 3, sid: e, grade: ee}
I/flutter (14196): Todo{id: 4, sid: r, grade: }
I/flutter (14196): Todo{id: 5, sid: hh, grade: kk}
模拟器的截图,添加新学生之前和添加新学生之后(最近的也不会出现,直到我再次添加另一个学生),
如果我没有遵循指南,我深表歉意,以前从未在这里真正发布过问题。
解决方案
你知道FutureBuilder吗?我建议将您包装ListView.builder
在未来的构建器中并将_loadTodos
函数作为未来传递。然后,您可以删除所有初始化 todos 的 initState 代码。
一般来说,我发现做异步工作initState
并不总是有效。UI 已经构建,并且不知道在异步工作完成时重新构建。另一种选择可能是setState
在异步函数完成待办事项后调用。我认为 FutureBuilder 是更好的方法。
如果您需要其他帮助,请告诉我。我可能会写一些给你。
推荐阅读
- python - Manim - 移动正方形后的奇怪角计算行为
- cypress - Cypress 的惯用方式来断言 DOM 中存在两个包含某些文本的元素
- javascript - IFrame 位置更改
- javascript - <%= %> HTML 标签的含义是什么?
- node.js - 带有 nodeJs 的 Keycloak-Connect Enforcer 不起作用
- git - Git push 说一切都是最新的,但远程更改没有反映!为什么?
- javascript - 如何从数组中找到对象数组
- python - 需要使用 python 根据修改日期检索 woocommerce 订单数据吗?
- python - 归一化单位,为什么我们在数值积分中使用它们?
- arrays - 将数据拖放到collectionView中