Android 在textWatcher中搜索列表时EditText滞后
这是我的Android 在textWatcher中搜索列表时EditText滞后,android,android-edittext,Android,Android Edittext,这是我的TextWatcher: searchBox.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged( CharSequence charSequence, int i, int i1, int i2) { } @Override public void
TextWatcher
:
searchBox.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged( CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(final CharSequence charSequence, int i, int i1, int i2) {
ArrayList<ProductInformation> newList = new ArrayList<>();
for (ProductInformation info : currentList)
if (info.getName().contains(charSequence))
newList.add(info);
productListAdapter.setNewData(newList);
}
@Override
public void afterTextChanged(Editable editable) {
}
});
searchBox.addTextChangedListener(新的TextWatcher(){
@凌驾
更改前的公共无效(CharSequence CharSequence,int i,int i1,int i2){
}
@凌驾
public void onTextChanged(final CharSequence CharSequence,int i,int i1,int i2){
ArrayList newList=新的ArrayList();
对于(产品信息:currentList)
if(info.getName().contains(charSequence))
添加(信息);
productListAdapter.setNewData(newList);
}
@凌驾
public void PostTextChanged(可编辑){
}
});
将此侦听器
添加到我的编辑文本
后,键入时会滞后。
我猜问题是在列表中搜索(列表中有40到60项)
我能做什么 如果输入的两个字符之间的时间差大于某个特定时间,则您可以使用以下逻辑避免搜索时间滞后:如果输入的时间差大于某个特定时间,则开始在列表中搜索以更新
productListAdapter
,如果不大于该时间,则保持空闲
以下是源代码:
startTime = System.currentTimeMillis();
endTime = System.currentTimeMillis();
searchBox.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged( CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(final CharSequence charSequence, int i, int i1, int i2) {
endTime = System.currentTimeMillis();
if(endTime - startTime >= 1000) {
ArrayList<ProductInformation> newList = new ArrayList<>();
for (ProductInformation info : currentList)
if (info.getName().contains(charSequence))
newList.add(info);
productListAdapter.setNewData(newList);
}
startTime = endTime;
}
@Override
public void afterTextChanged(Editable editable) {
}
});
startTime=System.currentTimeMillis();
endTime=System.currentTimeMillis();
addTextChangedListener(新的TextWatcher(){
@凌驾
更改前的公共无效(CharSequence CharSequence,int i,int i1,int i2){
}
@凌驾
public void onTextChanged(final CharSequence CharSequence,int i,int i1,int i2){
endTime=System.currentTimeMillis();
如果(结束时间-开始时间>=1000){
ArrayList newList=新的ArrayList();
对于(产品信息:currentList)
if(info.getName().contains(charSequence))
添加(信息);
productListAdapter.setNewData(newList);
}
开始时间=结束时间;
}
@凌驾
public void PostTextChanged(可编辑){
}
});
实时文本搜索对更好的性能有一些要求:
要求
- 您不应该立即开始搜索,因为用户键入速度非常快,并且下一个结果会立即覆盖上一个结果。运行多个搜索进程,但仅显示最后一个结果会浪费性能
- 尝试使搜索异步,即使它是网络请求或只是本地搜索,这样它不会损害用户界面,并且可以轻松取消
Timer
和TimerTask
延迟和取消输入
private Timer mRequestDelayTimer;
private TimerTask mSearchTask;
@Override
public void onTextChanged(final CharSequence query, int i, int i1, int i2) {
if (mRequestDelayTimer != null)
mRequestDelayTimer.cancel();
// If you do a async search, stop it here
stopSearch();
mRequestDelayTimer = new Timer();
mSearchTask = new TimerTask() {
@Override
public void run() {
startSearch(query);
}
};
mRequestDelayTimer.schedule(mSearchTask, 500);
}
private synchronized void startSearch(String query) {
// This is not run in UI thread. Use activity.runOnUiThread if you want to update the UI
// Call an AsyncTask to do an async search or run a sync loop search here
//ArrayList<ProductInformation> newList = new ArrayList<>();
//for (ProductInformation info : currentList)
// if (info.getName().contains(charSequence))
// newList.add(info);
//productListAdapter.setNewData(newList);
}
专用定时器mRequestDelayTimer;
专用TimerTask mSearchTask;
@凌驾
public void onTextChanged(最终字符序列查询,int i,int i1,int i2){
if(mRequestDelayTimer!=null)
mRequestDelayTimer.cancel();
//如果进行异步搜索,请在此处停止
停止搜索();
mRequestDelayTimer=新计时器();
mSearchTask=new TimerTask(){
@凌驾
公开募捐{
startSearch(查询);
}
};
mRequestDelayTimer.schedule(mSearchTask,500);
}
私有同步void startSearch(字符串查询){
//这不是在UI线程中运行的。如果要更新UI,请使用activity.runOnUiThread
//在此处调用AsyncTask执行异步搜索或运行同步循环搜索
//ArrayList newList=新的ArrayList();
//对于(产品信息:currentList)
//if(info.getName().contains(charSequence))
//添加(信息);
//productListAdapter.setNewData(newList);
}
解释
如果输入的每个字符都在500毫秒之内,它不会调用startSearch,因为计时器一直在延迟
如果用户休息时间超过500毫秒,startSearch
将从UI线程中调用。然后,如果用户在搜索仍在进行时开始键入,则将取消搜索
如果您在ArrayAdapter
中执行搜索和更新结果,它内置了一个Filter
进程,您可以通过覆盖getFilter
对其进行自定义。这个过滤器在后台自动运行,对每个字符进行取消输入,非常方便。参考:
您的实际实现可能不同,但想法是相同的对项目使用树映射或哈希映射而不是ArrayList。@Juan有什么区别吗?要在ArrayList中查找,它必须按顺序逐个检查,树映射使用二进制搜索,哈希映射应该一步解决查找问题。Hashmap与此不完全相同,但它是一个想法。感谢这个好的解决方案,我认为用户休息的最佳时间是250毫秒。很高兴我能提供帮助。延迟时间由您决定,我正在为每次搜索执行网络请求,因此保存网络数据和性能非常重要。甚至需要自定义缓存逻辑。Ref关于轻量级缓存如果需要:作为一个问题,上一次名为timer的ContextChanged将继续执行其工作,并且没有停止。您能更清楚地说,您的意思是
mSearchTask
没有取消吗?是的,确实如此