在textWatcher中搜索列表时,EditText会延迟

时间:2018-05-19 12:19:14

标签: android android-edittext

这是我的@RestController @RequestMapping("/movie") public class MovieController { @Autowired private MovieRepository movieRepository; public MovieController(MovieRepository movieRepository){ this.movieRepository = movieRepository; }//some CRUD methods @Repository public interface MovieRepository extends MongoRepository<Movie, String>{ public Movie findOneByName(String name); }

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) { } }); 添加到我的listener后,在输入时滞后。 我想问题是在列表中搜索(列表中有40到60个项目)。

我该怎么办?

2 个答案:

答案 0 :(得分:1)

您可以使用以下逻辑避免搜索时间滞后:如果输入的时间差 大于特定时间,则您开始在列表中搜索以进行更新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) {

        }
    });

答案 1 :(得分:0)

实时文本搜索对提高性能有一些要求:

<强>要求

  • 您不应该立即开始搜索,因为用户输入速度非常快,下一个结果会立即覆盖最后一个。多个搜索过程运行但仅显示最后的结果会浪费在性能上。

  • 尝试使搜索异步,即使它是网络请求或只是本地搜索,因此它不会损害用户界面并且可以轻松取消。

<强>解决方案

使用TimerTimerTask进行延迟,并在输入时取消

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

<强>解释

如果输入的每个字符都在500毫秒内,它就不会调用startSearch,因为计时器会一直延迟。

如果用户休息时间超过500毫秒,则会从UI线程中调出startSearch。然后,如果用户在搜索仍在进行时开始输入,则会被取消。

如果您在ArrayAdapter中执行搜索和更新结果,它内置了Filter进程,您可以通过覆盖getFilter来自定义它。此过滤器自动在后台运行,为每个字符输入取消,非常方便。参考:Custom getFilter in custom ArrayAdapter in android

您的实际实施可能会有所不同,但想法是相同的