如何处理Flutter中的大型列表搜索? [英] How to handle searching Large Lists in Flutter?

查看:78
本文介绍了如何处理Flutter中的大型列表搜索?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想问一下我应该如何在Flutter中处理大量清单.当我在要搜索的列表中确实很深的数据项上时,我的应用程序变得超级慢.我的列表是一个数据结构中超过70,000个对象.

以下是我搜索"列表的方式.

  Future< Iterable< SomeDataStruct>>_getAllData()异步{返回allData.where(((a)=>(a.dataTitle.toLowerCase().contains(querySearch.toLowerCase().trim()))));} 

使用FutureBuilder内部的ListView.builder构建列表.

当我搜索并填充列表深处的一个或多个结果时,该应用程序的运行速度非常慢,我单击列表项的时间很短,然后才执行onTap.而且,如果我需要更改搜索查询,则在单击TextField后,需要一些时间才能使软键盘重新显示.

我在哪里犯错或处理错了,我应该怎么做才能在不使应用无法忍受的情况下搜索庞大的列表.

更改代码后,如何使它不降低应用程序运行速度.这是正确的吗?

 字符串tempQuery;List< SomeDataStruct>searchResults = [];Future< List< SomeDataStruct>>_getAllData()异步{if(querySearch!= tempQuery){tempQuery = querySearch;searchResults = allData.where(((a)=>(a.dataTitle.toLowerCase().contains(querySearch.toLowerCase().trim()))).toList();}返回searchResults;} 

解决方案

包含昂贵的

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

将搜索支持限制在字符串的开头将已经大大提高了性能.另外,您可以创建辅助程序数据结构,在该结构中,整个值列表都以开头具有相同字符的部分拆分为多个部分.如果块仍然太大,则可以为第二个字符添加另一个级别.由于字符数有限,查找起来会很快.

使用数据库可能会减轻一些编程工作(维护索引).像SQLite这样的数据库可以与专门用于您的查询的索引一起使用.

分成较小的工作块,以允许框架执行其工作

如果您不能局限于字符串开头"搜索,您仍然可以将数据结构拆分为较小的块,并为每个异步块调用搜索.这样,在搜索下一个块之前,UI会呼吸",以重新呈现UI.搜索结果将逐步更新.

移出用户界面线程

另一种方法是启动另一个隔离并在那里进行搜索.另一个隔离可以在另一个CPU(核心)上运行,因此在搜索时不会阻塞UI线程.这样,就不必拆分成大块了.尽管逐步更新UI而不是让用户等到整个搜索结果可用之前,仍然可能是有利的.

另请参见

缓存

将搜索结果保存在内存中也可能有助于提高性能.例如,如果用户输入 foo 然后按退格键,则可以对先前已经计算出的 fo 重新使用搜索结果,但这仅在某些情况下有用.

测量

当然,另一个重要的点是进行基准测试.无论您尝试如何提高性能,都应创建基准以了解哪些措施具有什么效果,以及是否值得.您将学到很多有关您的方案,数据,Dart等的信息,这将使您能够做出明智的决定.

I want to ask how I should handle a large list in Flutter. My app gets super slow when I am at a data item that is really deep in the list which I am searching. My list is 70,000+ objects of a data structure large.

The following is how I am "Searching" the list.

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

Building the list using a ListView.builder inside of a FutureBuilder.

When I search and a result or results from deep inside the list are populated the app is extremely slow to the point where I click a list item and it takes few seconds before it does its onTap. And if I need to change the search query it takes time for the soft keyboard to come back up after I click on the TextField.

Where am I making a mistake or handling this wrong, what should I do to have my huge list searchable without making app unbearable.

EDIT: How I made it not slow down the app after change to code. Is this correct?

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;
  }

解决方案

Contains is expensive

Contains-queries are expensive, because every entry needs to be checked at every position (up to value.length - searchTerm.length) if the search term can be found.

Limiting search support to the beginning of the string would improve performance a lot already. In addition you could create helper data-structures where the whole list of values is split into parts with the same character at the beginning. If the chunks are still too big another level could be added for the 2nd character. The lookup would be fast because there are only a limited number of characters.

Using a database might take off some programming work (maintaining indexes). A database like SQLite could be used with indexes specialized to your kind of queries.

Split into smaller chunks of work to allow the framework to do its work

If you can't limit to "beginning of string"-search, you could still split the data structure into smaller chunks and invoke search for each chunk async. This way the UI gets "some air to breath" to re-render the UI before the next chunk is searched. The search result would be updated incrementally.

Move work off the UI thread

Another way would be to start up another isolate and do the search there. Another isolate can run on another CPU (core) and therefore would not block the UI thread when searching. This way it wouldn't be necessary to split into chunks. It might still be advantageous though to incrementally update the UI instead of keeping the user waiting until the whole search result becomes available.

See also

Caching

It might also help improve performance to keep search results in memory. For example if the user enters foo and then presses backspace then you could reuse the search result for fo that you previously calculated already, but that only helps in some cases.

Measuring

Another important point of course is to do benchmarking. Whatever you try to improve performance, create benchmarks to learn what measures have what effect and if it's worth it. You'll learn a lot about your scenario, your data, Dart, ..., and this will allow you to make good decisions.

这篇关于如何处理Flutter中的大型列表搜索?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆