如何处理在 Flutter 中搜索大列表?

pun*_*ife 6 dart flutter

我想问一下我应该如何处理 Flutter 中的大列表。当我位于我正在搜索的列表中非常深的数据项时,我的应用程序变得非常慢。我的清单是一个大数据结构的 70,000 多个对象。

以下是我“搜索”列表的方式。

Future<Iterable<SomeDataStruct>> _getAllData() async {
    return allData.where((a) => (a.dataTitle.toLowerCase().contains(querySearch.toLowerCase().trim())));
}
Run Code Online (Sandbox Code Playgroud)

使用 FutureBuilder 中的 ListView.builder 构建列表。

当我搜索并填充列表深处的一个或多个结果时,应用程序非常慢,以至于我单击列表项时,它需要几秒钟才能执行 onTap。如果我需要更改搜索查询,则在单击 TextField 后软键盘需要时间才能恢复。

我在哪里犯了错误或处理这个错误,我应该怎么做才能让我的庞大列表可搜索而不使应用程序无法忍受。

编辑: 更改代码后,我如何使它不减慢应用程序的速度。这样对吗?

String tempQuery;
List<SomeDataStruct> searchResults = [];
Future<List<SomeDataStruct>> _getAllData() async {
    if(querySearch!=tempQuery) {
      tempQuery = querySearch;
      searchResults = allData.where((a) => (a.dataTitle.toLowerCase().contains(querySearch.toLowerCase().trim()))).toList();
    }
    return searchResults;
  }
Run Code Online (Sandbox Code Playgroud)

Gün*_*uer 7

包含是昂贵的

包含查询很昂贵,因为如果可以找到搜索词,则需要在每个位置(最多value.length- searchTerm.length)检查每个条目。

将搜索支持限制在字符串的开头已经可以大大提高性能。此外,您可以创建辅助数据结构,其中整个值列表在开头分成具有相同字符的部分。如果块仍然太大,可以为第二个角色添加另一个级别。查找会很快,因为只有有限数量的字符。

使用数据库可能会减少一些编程工作(维护索引)。像 SQLite 这样的数据库可以与专门针对您的查询类型的索引一起使用。

拆分成更小的工作块以允许框架完成其工作

如果您不能限制为“字符串开头”-搜索,您仍然可以将数据结构拆分为更小的块并为每个块异步调用搜索。这样,在搜索下一个块之前,UI 会获得“呼吸的空气”以重新渲染 UI。搜索结果将逐步更新。

将工作移出 UI 线程

另一种方法是启动另一个隔离并在那里进行搜索。另一个隔离可以在另一个 CPU(核心)上运行,因此在搜索时不会阻塞 UI 线程。这样就不需要分成块了。尽管增量更新 UI 而不是让用户等待直到整个搜索结果可用,但它可能仍然是有利的。

也可以看看

缓存

将搜索结果保存在内存中也可能有助于提高性能。例如,如果用户输入foo然后按退格键,那么您可以重复使用fo之前计算过的搜索结果,但这仅在某些情况下有帮助。

测量

另一个重点当然是做基准测试。无论您尝试提高性能,创建基准以了解哪些措施会产生什么效果以及是否值得。你会学到很多关于你的场景、你的数据、Dart,......,这将使你能够做出正确的决定。


jul*_*nap -2

也许这样:

ListView.builder(
  itemBuilder: (BuildContext context, int index) {
    return Text(data[index]);
  },
)
Run Code Online (Sandbox Code Playgroud)