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:26

You can also use TextWatcher interface and create your custom class that implements it to re-use many times your CustomTextWatcher and also you can pass views or whatever you might need to its constructor:

public abstract class CustomTextWatcherimplements TextWatcher { //Notice abstract class so we leave abstract method textWasChanged() for implementing class to define it

    private final TextView myTextView; //Remember EditText is a TextView so this works for EditText also


    public AddressTextWatcher(TextView tView) { //Notice I'm passing a view at the constructor, but you can pass other variables or whatever you need
        myTextView= tView;

    }

    private Timer timer = new Timer();
    private final int DELAY = 500; //milliseconds of delay for timer

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

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(final Editable s) {
        timer.cancel();
        timer = new Timer();

        timer.schedule(

                new TimerTask() {
                    @Override
                    public void run() {
                        textWasChanged();
                    }
                },
                DELAY

        );
    }

    public abstract void textWasChanged(); //Notice abstract method to leave implementation to implementing class

}

Now in your activity you can use it like this:

    myEditText.addTextChangedListener(new CustomTextWatcher(myEditText) { //Notice I'm passing in constructor of CustomTextWatcher myEditText I needed to use
        @Override
        public void textWasChanged() {
            //doSomething(); this is method inside your activity
        }
    });
查看更多
Bombasti
3楼-- · 2019-01-30 23:32

Better use Handler with postDelayed() method. In the android's implementation Timer will create new thread each time to run the task. Handler however has its own Looper that can be attached to whatever thread we wish, so we won't pay extra cost to create thread.

Example

 Handler handler = new Handler(Looper.getMainLooper() /*UI thread*/);
 Runnable workRunnable;
 @Override public void afterTextChanged(Editable s) {
    handler.removeCallbacks(workRunnable);
    workRunnable = () -> doSmth(s.toString());
    handler.postDelayed(workRunnable, 500 /*delay*/);
 }

 private final void doSmth(String str) {
    //
 }
查看更多
一纸荒年 Trace。
4楼-- · 2019-01-30 23:33

How do you determine that they have finished writing? That the edittext loses focus? Then there is setOnFocusChangedListener.

Responding to latest edit in question: If you want to wait a specific time after the latest key stroke, then you have to start up a thread at the first keypress (use TextWatcher). Constantly register the time of the latest key stroke. Let the thread sleep to the the time of the latest keystroke + 0.5 seconds. If the timestamp of the latest keystroke has not been updated, do whatever you had intended.

查看更多
地球回转人心会变
5楼-- · 2019-01-30 23:35

If you want to skip textWatcher for the first time only then add following code: This will allow textWatcher make any change from the second time.

    Boolean firstchange=false;
    profileEmailEditText.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    if (firstchange) {
                        emailAlertText.setVisibility(View.VISIBLE);
                    }
                    else {
                        firstchange=true;
                    }
                }

                @Override
                public void afterTextChanged(Editable s) {

                }
            });
查看更多
你好瞎i
6楼-- · 2019-01-30 23:40

Using timer for your case is not the best solution because of creating new object everytime. According to Timer documentation(http://developer.android.com/reference/java/util/Timer.html) it's better to use ScheduledThreadPoolExecutor -

"Timers schedule one-shot or recurring tasks for execution. Prefer ScheduledThreadPoolExecutor for new code."

Here is better approach

Runnable runnabledelayedTask = new Runnable(){
    @Override
    public void run(){
        //TODO perform any operation here
    }
};

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 final long DELAY = 500; // milliseconds

        @Override
        public void afterTextChanged(final Editable s) {
        ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(1);
        ScheduledFuture sf = scheduledPool.schedule(callabledelayedTask, DELAY, TimeUnit.MILLISECONDS);
        //you can cancel ScheduledFuture when needed
        }
    }
);
查看更多
Emotional °昔
7楼-- · 2019-01-30 23:41

that is the event while and after finish of typing ... add a textWatcher and in the onTextChanged method put :

if (charSequence.length() > 0){// your code }

查看更多
登录 后发表回答