Flutter 颤振提供程序-重建列表项而不是列表视图
我正在使用提供商软件包来管理我的应用程序业务逻辑,但我遇到了一个问题,我的整个ListView正在重建,而不是单个ListTile。以下是让您更好理解的UI: 当前,如果我滚动到列表的底部,点击最后一项的复选框,我看不到复选框切换的动画,滚动跳到屏幕的顶部,因为整个小部件已重建如何使用提供程序,以便仅重建单个ListTile,而不是重建列表中的所有项目? 以下是一些相关代码:Flutter 颤振提供程序-重建列表项而不是列表视图,flutter,Flutter,我正在使用提供商软件包来管理我的应用程序业务逻辑,但我遇到了一个问题,我的整个ListView正在重建,而不是单个ListTile。以下是让您更好理解的UI: 当前,如果我滚动到列表的底部,点击最后一项的复选框,我看不到复选框切换的动画,滚动跳到屏幕的顶部,因为整个小部件已重建如何使用提供程序,以便仅重建单个ListTile,而不是重建列表中的所有项目? 以下是一些相关代码: class MyApp extends StatelessWidget { @override Widget
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Checklist',
theme: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.indigo[500],
accentColor: Colors.amber[500],
),
home: ChecklistHomeScreen(),
),
providers: [
ChangeNotifierProvider(
create: (ctx) => ChecklistsProvider(),
),
],
);
}
}
class ChecklistHomeScreen扩展StatefulWidget{
@凌驾
_ChecklistHomeScreenState createState()=>\u ChecklistHomeScreenState();
}
类_ChecklistHomeScreenState扩展状态{
void createList(BuildContext上下文,字符串listName){
if(listName.isNotEmpty){
Provider.of(context).addChecklist(listName);
}
}
@凌驾
小部件构建(构建上下文){
final _checklists=提供者.of(上下文).checklists;
最终_scaffoldKey=GlobalKey();
ScrollController\u ScrollController=
PrimaryScrollController.of(上下文)??ScrollController();
返回脚手架(
钥匙:_scaffoldKey,
正文:自定义滚动视图(
控制器:\ u滚动控制器,
条子:[
滑杆(
浮动:是的,
错,,
标题:文本(“您的列表”),
标题:对,
行动:[
弹出菜单按钮(
itemBuilder:(ctx)=>null,
),
],
),
可重排序列表(
委托:ReorderableSliverChildBuilderDelegate(
(ctx,i)=>\u buildListItem(\u检查表[i],i),
childCount:_checklists.length,
),
onReorder:(int-oldIndex,int-newIndex){
设置状态(){
最终检查表=_检查表。删除(旧索引);
_检查表。插入(新索引、检查表);
});
},
),
],
),
抽屉(
child:null,
),
浮动操作按钮:浮动操作按钮(
子:图标(Icons.add),
onPressed:null,
),
);
}
小部件_buildListItem(检查表列表,int listIndex){
可驳回的回报(
key:ObjectKey(list.id),
方向:DismissDirection.endToStart,
背景:卡片(
海拔:0,
子:容器(
对齐:对齐方向.centerEnd,
颜色:主题。背景。强调颜色,
孩子:填充(
填充:来自LTRB(0.0,0.0,10.0,0.0)的边缘设置,
子:图标(
图标。删除,
颜色:颜色,白色,
),
),
),
),
孩子:卡片(
孩子:ListTile(
onTap:null,
标题:文本(列表名称),
前导:复选框(
值:list.completed,
一旦更改:(值){
提供者(上下文)
.toggleCompletedStatus(list.id,list.completed);
},
),
尾随:图标按钮(
图标:图标(更多图标),
onPressed:null,
),
),
),
onDismissed:(方向){
_onDeleteList(列表、列表索引);
},
);
}
作废删除列表(检查表列表、int列表索引){
Scaffold.of(context.removeCurrentSnackBar();
Scaffold.of(上下文).showSnackBar(
小吃条(
行动:SnackBarAction(
标签:“撤消”,
已按下:(){
提供者(上下文)
.检查表(列表、列表索引);
},
),
内容:文本(
“已删除列表”,
样式:TextStyle(颜色:Theme.of(context).accentColor),
),
),
);
}
}
带有ChangeNotifier的类检查列表Provider{
最终ChecklistRepository _repository=ChecklistRepository();//单例
UnmodifiableListView获取检查列表=>UnmodifiableListView(_repository.getChecklists());
void addChecklist(字符串名称){
_储存库。添加清单(名称);
notifyListeners();
}
无效删除检查表(内部id){
_储存库。删除清单(id);
notifyListeners();
}
void toggleCompletedStatus(int-id,bool-completed){
最终列表=检查列表.firstWhere((c)=>c.id==id);
如果(列表!=null){
list.completed=已完成;
_repository.updateChecklist(列表);
notifyListeners();
}
}
}
我应该说我理解为什么这是当前的行为,我只是不确定正确的方法来确保只重建我想要更新的列表项,而不是整个屏幕。
我也读过关于
消费者的内容,但我不确定如何将其应用到我的实现中。消费者基本上允许您使用对更改通知程序所做的任何更改。最好的做法是将使用者尽可能深入地嵌入到构建方法中。这样,只有包装好的小部件才能重新构建。这份文件很好地解释了这一点:
尝试将复选框小部件包装到消费者小部件中。只应重新生成复选框
Consumer<ChecklistsProvider>(
builder: (context, provider, _) {
return Checkbox(
value: list.completed,
onChanged: (value) {
provider.toggleCompletedStatus(list.id, list.completed);
},
);
},
),
消费者(
生成器:(上下文,提供程序,u41;{
返回复选框(
值:list.completed,
一旦更改:(值){
provider.toggleCompletedStatus(list.id,list.completed);
},
);
},
),
如果您希望重新构建ListTile和复选框,只需将ListTile包装到使用者中即可我解决此问题的方法是创建另一个提供程序
类,该类将仅由每个ListTile
的复选框
小部件使用
leading: Consumer<ChecklistTileProvider>(
builder: (ctx, provider, _) => Checkbox(
value: list.completed,
onChanged: (value) {
provider.toggleCompletedStatus(list.id, value);
},
),
),
领先:消费者(
生成器:(ctx,提供程序,)=>复选框(
值:list.completed,
Consumer<ChecklistsProvider>(
builder: (context, provider, _) {
return Checkbox(
value: list.completed,
onChanged: (value) {
provider.toggleCompletedStatus(list.id, list.completed);
},
);
},
),
leading: Consumer<ChecklistTileProvider>(
builder: (ctx, provider, _) => Checkbox(
value: list.completed,
onChanged: (value) {
provider.toggleCompletedStatus(list.id, value);
},
),
),