flutter - ListView.build 过滤后渲染错误的元素
问题描述
我对 Flutter 上的 ListView.builder 有疑问。每当我按字符串模式过滤元素时,我总是会在列表中呈现错误的项目,尽管预期的长度是正确的。这是我的代码:
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(105.0),
child: Observer(builder: (_) {
return Column(
children: <Widget>[
searchBar(), // StreamBuilder
filtroFavorito(), // StreamBuilder
],
);
})),
body: SafeArea(
child: AppDefaultPadding(
child: Observer(builder: (_) => buildListView()),
),
),
);
}
searchBar() {
return AppBar(
title: !controller.isSearching
? Text(widget.title)
: Container(
height: 40.0,
child: TextField(
onChanged: (String? text) {
controller.filtra(text != null ? text : '');
print("First text field: $text");
},
decoration: new InputDecoration(
filled: true,
fillColor: Colors.white.withOpacity(0.5),
prefixIcon: new Icon(
Icons.search,
color: Colors.white,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(
width: 0, style: BorderStyle.none)),
enabledBorder: UnderlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: Colors.transparent, width: 0),
),
focusedBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: Colors.transparent, width: 0),
),
contentPadding:
EdgeInsets.only(left: 15, bottom: 0, top: 7, right: 15),
hintText: 'Pesquisa...',
hintStyle: TextStyle(fontSize: 17, color: Colors.white)),
)),
actions: <Widget>[
IconButton(
icon: Icon(
!controller.isSearching ? Icons.search : Icons.close,
color: Colors.white,
),
onPressed: () {
controller.isSearching
? controller.isSearching = false
: controller.isSearching = true;
controller.filtra('');
//_searchPressed();
},
)
],
);
}
buildListView() {
return ListView.builder(
itemCount: controller.listaLinhas.length,
itemBuilder: (context, i) {
var item = controller.listaLinhas[i];
return LinhaItemWidget(
linha: item,
onChange: (bool val) {
print('novo valor para o elemento ${item.codLinha} : $val');
controller.setaFavorito(i, val);
},
onClick: (LinhaModel val) {
if (item.sentido!.length > 1) {
controller.sentidoSelecionado = null;
popup(item);
} else
controller.abreFormulario(item);
},
);
},
);
}
现在控制器(listaLinhas 是一个 ObservableList):
@action
filtra(String v) {
isFiltroFavorito = false;
listaLinhas = listaLinhasAux
.where((i) => '${i.codLinha} ${i.nomeLinha}'
.toLowerCase()
.contains(v.toLowerCase()))
.toList()
.asObservable();
}
示例1:如果我有一个列表,例如[香蕉,芒果,鳄梨,西瓜,甜瓜],如果我按“甜瓜”过滤,则显示香蕉和芒果!
示例 2:在同一个列表中,如果我按“芒果”过滤,则会显示香蕉。
我的 filtra 方法工作正常,预期结果正在被过滤并显示在控制台上。我的 Flutter 版本是 2.5.1。
解决方案
我的建议是你需要在构建时使用键LinhaItemWidget
(将键添加到它的构造函数并传递ValueKey
项目的 id 或类似的东西)。
问题是颤振试图优化渲染过程,它重用旧的小部件,而不是从头开始重建所有东西(这正是基于你的水果示例的样子)。为了更好地了解发生了什么,请查看此视频。
推荐阅读
- r - R Shiny - 在 Reactive 中使用 eventReactive 输出
- swift - 为什么 Swift 解释器为抛出运行时错误的实例提供内存位置,而不是类名?
- javascript - 如何在javascript中获取时区偏移量?
- sql - Oracle 每个值创建 N 行
- html - 带有 if 条件的 Webscrape VBA
- c++ - 为什么我们返回指向节点的指针而不是 avl 树实现的 void 函数?
- sql - 使用 powershell 将数据插入到 ODBC 目标
- string - 停止将 formData 字符串转换为日期字符串表示形式
- angular - 在 Postman 中工作时,根据来自 Angular HttpClient 中服务器的响应,添加标头似乎失败
- php - 使用 finfo->buffer() 确定 mime 类型时内存使用率高,但仅适用于某些文本文件类型?