在SearchView中调节onQueryTextChange

问题描述 投票:8回答:6

什么是“限制”onQueryTextChange的最佳方式,以便我的performSearch()方法每秒只调用一次,而不是每次用户输入?

public boolean onQueryTextChange(final String newText) {
    if (newText.length() > 3) {
        // throttle to call performSearch once every second
        performSearch(nextText);
    }
    return false;
}
java android search searchview android-search
6个回答
18
投票

基于aherrick的代码,我有一个更好的解决方案。而不是使用布尔'canRun',声明一个runnable变量,并在每次更改查询文本时清除处理程序上的回调队列。这是我最终使用的代码:

@Override
public boolean onQueryTextChange(final String newText) {
    searchText = newText;

    // Remove all previous callbacks.
    handler.removeCallbacks(runnable);

    runnable = new Runnable() {
        @Override
        public void run() {
            // Your code here.
        }
    };
    handler.postDelayed(runnable, 500);

    return false;
}

6
投票

我找到了使用RxJava的解决方案,特别是它的debounce运算符。

有了Jake Wharton的方便的RxBinding,我们将拥有:

RxSearchView.queryTextChanges(searchView)
        .debounce(1, TimeUnit.SECONDS) // stream will go down after 1 second inactivity of user
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer<CharSequence>() {
            @Override
            public void accept(@NonNull CharSequence charSequence) throws Exception {
                // perform necessary operation with `charSequence`
            }
        });

4
投票

如果您使用Kotlin和协同程序,您可以执行以下操作:

var queryTextChangedJob: Job? = null

...

fun onQueryTextChange(query: String): Boolean {

    queryTextChangedJob?.cancel()

    queryTextChangedJob = launch(Dispatchers.Main) {
        delay(500)
        performSearch(query)
    }
}

2
投票

你可以用RxJava轻松实现它。此外,您将需要RxAndroidRxBinding(但如果您使用的是RxJava,则可能已经在项目中使用了它们)。

RxTextView.textChangeEvents(yourEditText)
          .debounce(1, TimeUnit.SECONDS)
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe(performSearch());

Here是Kaushik Gopal的完整例子。


0
投票

1)创建抽象类:

public abstract class DelayedOnQueryTextListener implements SearchView.OnQueryTextListener {

    private Handler handler = new Handler();
    private Runnable runnable;

    @Override
    public boolean onQueryTextSubmit(String s) {
        return false;
    }

    @Override
    public boolean onQueryTextChange(String s) {
        handler.removeCallbacks(runnable);
        runnable = () -> onDelayerQueryTextChange(s);
        handler.postDelayed(runnable, 400);
        return true;
    }

    public abstract void onDelayerQueryTextChange(String query);
}

2)像这样设置:

searchView.setOnQueryTextListener(new DelayedOnQueryTextListener() {
        @Override
        public void onDelayerQueryTextChange(String query) {
            // Handle query
        }
    });

-1
投票

我最终得到了类似于下面的解决方案。这样它应该每半秒发射一次。

        public boolean onQueryTextChange(final String newText) {

            if (newText.length() > 3) {

                if (canRun) {
                    canRun = false;
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {

                            canRun = true;
                            handleLocationSearch(newText);
                        }
                    }, 500);
                }
            }

            return false;
        }
© www.soinside.com 2019 - 2024. All rights reserved.