Flutter Dismissible和FutureBuilder不能一起工作
这是一个复杂的问题,但我会尽力解释 我的项目使用一个sqflite数据库。此特定页面根据数据库中的数据返回一个可拒绝的小部件列表。以下是我读取数据的方式:Flutter Dismissible和FutureBuilder不能一起工作,flutter,dart,future,sqflite,dismissible,Flutter,Dart,Future,Sqflite,Dismissible,这是一个复杂的问题,但我会尽力解释 我的项目使用一个sqflite数据库。此特定页面根据数据库中的数据返回一个可拒绝的小部件列表。以下是我读取数据的方式: 类TaskListState扩展状态{ DBProvider DBProvider=新的DBProvider(); 未来所有任务; @凌驾 void initState(){ allTasks=dbProvider.getAllTasks(); super.initState(); } 无效更新(){ 设置状态(){ allTasks=dbP
类TaskListState扩展状态{
DBProvider DBProvider=新的DBProvider();
未来所有任务;
@凌驾
void initState(){
allTasks=dbProvider.getAllTasks();
super.initState();
}
无效更新(){
设置状态(){
allTasks=dbProvider.getAllTasks();
});
}
//建造
}
TaskList小部件返回一个带有FutureBuilder的页面,FutureBuilder使用数据库中的数据构建ListView.builder。ListView构建可忽略的小部件。解除可解除的小部件将更新数据库中的一行,并再次读取数据以更新列表
TaskListState的生成方法
@覆盖
小部件构建(构建上下文){
返回列表视图(
物理:常量AlwaysScrollablePhysics(),
儿童:[
//其他小部件,例如列表的标题
),
未来建设者(
未来:所有任务,
生成器:(上下文,快照){
if(snapshot.hasError){
返回文本(“数据有错误”);
}如果(!snapshot.hasData){
返回中心(
子对象:CircularProgressIndicator(),
);
}否则{
return pendingList(Task.filterByDone(false,Task.filterByDate(Datetime.now,snapshot.data));//过滤数据以匹配当前日期
}
},
),
//其他小部件
],
);
}
悬而未决的名单
Widget挂起列表(列出任务){
//如果“任务”为空,则返回文本小部件的一些代码
返回ListView.separated(
separatorBuilder:(上下文,索引){
回流隔板(高度:2.0);
},
itemCount:tasks.length,
物理学:const NeverScrollableScrollPhysics(),
收缩膜:对,
itemBuilder:(上下文,索引){
可驳回的回报(
//可驳回的背景、其他非必需参数
key:key(UniqueKey().toString()),
onDismissed:(方向)异步{
Task toRemove=tasks[index];//保存已解除的任务,以便进行后续操作
int removeIndex=tasks.indexWhere((task)=>task.id==toRemove.id);
tasks.removeAt(removeIndex);//删除已解除的任务
if(direction==DismissDirection.endToStart){
rateTask(toRemove)。然后((value)=>update());//rateTask是更新任务的函数,它将从列表中删除
}
如果(方向==解除方向.开始结束){
dbProvider.update(/*用于更新所选任务的代码*/)。然后((值)=>update());
}
},
孩子:ListTile(
//列表块详细信息
),
);
},
);
}
问题是(可能是错误的解释,我还是个新手):
关闭小部件实际上是将其从列表中删除。用户解除任务后,任务将从列表中“可视化”删除,并调用update()
方法,该方法调用setState()
。调用setState()
会导致FutureBuilder再次生成,但在FutureBuilder再次生成时,dbProvider.getAllTasks()
调用尚未完成。因此,FutureBuilder会传递旧的快照,这会导致ListView重新生成刚刚被取消的任务。这会导致被撤销的列表在被撤销后立即出现,这看起来令人毛骨悚然且错误
我不知道如何解决这个问题。任何帮助都将不胜感激。通过不使用FutureBuilder并在查询完成后调用setState找到了解决方法 该状态现在包含一个声明为空的
列表,而不是Future
类TaskListState扩展状态{
DBProvider DBProvider=新的DBProvider();
DateTime now=DateTime.now();
列出今天的任务;
//建造
}
update()
函数更改如下
void update()异步{
Future futureTasks=dbProvider.getByDate(现在);//首先进行查询
未来任务。然后((数据){
列表任务=新列表();
对于(int i=0;i
这样我就可以在未来完成之前不重建小部件,这就是我遇到的问题
我完全删除了FutureBuilder,Listview.builder只是根据状态中存储的列表进行构建
@覆盖
小部件构建(构建上下文){
如果(TodayStasks==null){
更新();
返回中心(
子对象:CircularProgressIndicator(),
);
}//如果列表尚未初始化,则进行查询
返回列表视图(
物理:常量AlwaysScrollablePhysics(),
儿童:[
//其他小部件
pendingList(Task.filterByDone(false,TodayStasks)),
],
);
}
这种方法完全解决了我的问题,而且我认为它比使用FutureBuilder要好,以防将来必须在小部件再次构建之前完成 我遇到了完全相同的问题,我使用了sqflite,它与期货
一起使用FutureBuilder
和Dismissible
一起用于我的列表视图
。被删除的列表项将被删除,然后重新出现一帧,然后再次消失。我遇到了一个问题:
这建议从快照数据本身中删除列表项:
return FutureBuilder<List<FolderModel>>(
future: Provider.of<FoldersProvider>(context).getFolders(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, i) {
final folder = snapshot.data[i];
return Dismissible(
onDismissed: (direction) {
snapshot.data.removeAt(i); // to avoid weird future builder issue with dismissible
Provider.of<FoldersProvider>(context, listen: false).deleteFolder(folder.id);
},
background: Card(
margin: EdgeInsets.symmetric(vertical: 8),
elevation: 1,
child: Container(
alignment: AlignmentDirectional.centerStart,
color: Theme.of(context).accentColor,
child: Padding(
padding: EdgeInsets.fromLTRB(15.0, 0.0, 0.0, 0.0),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
),
),
key: UniqueKey(),
direction: DismissDirection.startToEnd,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
elevation: 1,
child: ListTile(
title: Text(folder.folderName),
leading: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.folder,
color: Theme.of(context).accentColor,
),
],
),
subtitle: folder.numberOfLists != 1
? Text('${folder.numberOfLists} items')
: Text('${folder.numberOfLists} item'),
onTap: () {},
),
),
);
},
);
},
);
返回FutureBuilder(
未来:供应商。