How can I do something, 0.5 second after text chan

2019-01-30 23:12发布

I am filtering my list using an EditText. I want to filter the list 0.5 second after user has finished typing in EditText. I used the afterTextChanged event of TextWatcher for this purpose. But this event rises for each character changes in EditText.

What should I do?

10条回答
劫难
2楼-- · 2019-01-30 23:41

You can use EditorActionListener for that purpose.

editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            //Do something here
            return true;
        }
        return false;
    }
});
查看更多
叛逆
3楼-- · 2019-01-30 23:43

You can use RxBindings, it's the best solution. See guide to RxJava operator debounce, I'm sure that will do great in your case.

RxTextView.textChanges(editTextVariableName)
            .debounce(500, TimeUnit.MILLISECONDS)
            .subscribe(new Action1<String>() {
                @Override
                public void call(String value) {
                    // do some work with the updated text
                }
            });

http://reactivex.io/documentation/operators/debounce.html

查看更多
Deceive 欺骗
4楼-- · 2019-01-30 23:45
editText.addTextChangedListener(
    new TextWatcher() {
        @Override public void onTextChanged(CharSequence s, int start, int before, int count) { }
        @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

        private Timer timer=new Timer();
        private final long DELAY = 1000; // milliseconds

        @Override
        public void afterTextChanged(final Editable s) {
            timer.cancel();
            timer = new Timer();
            timer.schedule(
                new TimerTask() {
                    @Override
                    public void run() {
                        // TODO: do what you need here (refresh list)
                        // you will probably need to use runOnUiThread(Runnable action) for some specific actions
                    }
                }, 
                DELAY
            );
        }
    }
);

The trick is in canceling and re-scheduling Timer each time, when text in EditText gets changed. Good luck!

UPDATE For those interested in how long to set the delay, see this post.

查看更多
ゆ 、 Hurt°
5楼-- · 2019-01-30 23:49

Non of the above solution worked for me.

I needed a way for TextWatcher to not fire on every character I input inside my search view and show some progress, meaning I need to access UI thread.

private final TextWatcher textWatcherSearchListener = new TextWatcher() {
    final android.os.Handler handler = new android.os.Handler();
    Runnable runnable;

    public void onTextChanged(final CharSequence s, int start, final int before, int count) {
        handler.removeCallbacks(runnable);
    }

    @Override
    public void afterTextChanged(final Editable s) {
        //show some progress, because you can access UI here
        runnable = new Runnable() {
            @Override
            public void run() {
                //do some work with s.toString()
            }
        };
        handler.postDelayed(runnable, 500);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
};

Removing Handler on every onTextChanged (which is called when the user inputs a new character). afterTextChanged is called after the text has been changed inside input field where we can start new Runnable, but will cancel it if user types more characters (For more info, when these callback are called, see this). If user doesn't input anymore characters, interval will pass in postDelayed and it will call work you should do with that text.

This code will run only once per interval, not for every key user inputs. Hope it helps someone in the future.

查看更多
登录 后发表回答