我正在尝试实现自动完成功能,以便在我的应用中选择地点。为此,我使用Here Maps API。目前,我有一个TextField
:
onChanged: (query){
print("Current value is: ${query}");
if(query) { getPlacesFromHereMaps(query); }
},
这里,每次用户输入字母时,都会在此处调用自动完成API。
因此,如果用户键入“ New York”,则意味着应用程序将调用API约8次,而我发现这太多了。有没有办法对此进行优化?
答案 0 :(得分:1)
onChanged
正在完成其工作。根据文档:
每当用户更改时,文本字段就会调用onChanged回调 字段中的文本。如果用户指示输入完毕 在字段中(例如,通过按下软键盘上的按钮), 文本字段调用onSubmitted回调。
如果要优化,可以执行以下操作:
onChanged(query) {
if (query.length < 2) return;
// if the length of the word is less than 2, stop executing your API call.
// rest of your code
getPlacesFromHereMaps(query);
}
答案 1 :(得分:1)
每当用户结束键入单词或每3(或2)个字符后,您都可以调用API。
但是,当用户提交查询(使用onSubmitted
)时,请不要忘记调用API。
解决方案代码:
onChanged: (query){
print("Current value is: ${query}");
if((query.length%3==0)||(query[query.length-1]==' ')) { getPlacesFromHereMaps(query); }
onSubmitted: (query){
getPlacesFromHereMaps(query);
}
},
=========
替代解决方案:
根据@Karim Elghamry的建议和@CopsOnRoad的关注,您甚至可以使用反跳来改善UX。
在小部件状态下,声明一个控制器和计时器:
final _searchQuery = new TextEditingController();
Timer _debounce;
添加侦听器方法:
_onSearchChanged() {
if (_debounce?.isActive ?? false) _debounce.cancel();
_debounce = Timer(const Duration(milliseconds: 500), () {
getPlacesFromHereMaps(query);
});
}
将方法挂钩并取消挂钩到控制器:
@override
void initState() {
super.initState();
_searchQuery.addListener(_onSearchChanged);
}
@override
void dispose() {
_searchQuery.removeListener(_onSearchChanged);
_searchQuery.dispose();
super.dispose();
}
在构建树中,将控制器绑定到TextField:
child: TextField(
controller: _searchQuery,
[...]
)
答案 2 :(得分:0)
考虑流行的节点包“ debounce”,以下是简单的实现
/// Implementation of well known 'Debounce' node package in Dart
class Debounce {
final Function _function;
final Duration _duration;
Timer _timer;
int _lastCompletionTime;
Debounce(this._duration, this._function)
: assert(_duration != null, "Duration can not be null"),
assert(function != null, "Function can not be null");
void schedule() {
var now = DateTime.now().millisecondsSinceEpoch;
if (_timer == null || (_timer != null && !_timer.isActive)) {
_lastCompletionTime = now + _duration.inMilliseconds;
_timer = Timer(_duration, _function);
} else {
_timer?.cancel(); // doesn't throw exception if _timer is not active
int wait = _lastCompletionTime - now; // this uses last wait time, so we need to wait only for calculated wait time
_lastCompletionTime = now + wait;
_timer = Timer(Duration(milliseconds: wait), _function);
}
}
}
用法:
1。定义
var debounce = Debounce(Duration(seconds: 1), () {
getPlacesFromHereMaps(query);
});
2。每次值更改时调用
onChanged: (query){
print("Current value is: ${query}");
if(query.trim().length > 3) { d.schedule(); }
}