Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 在textWatcher中搜索列表时EditText滞后_Android_Android Edittext - Fatal编程技术网

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
没有取消吗?是的,确实如此