¿Cómo puedo hacer algo, 0.5 segundo después de que el texto cambió en mi EditText?

Estoy filtrando mi lista usando un EditText. Quiero filtrar la lista 0.5 segundos después de que el usuario haya terminado de escribir en EditText . Utilicé el evento TextWatcher de TextWatcher para este propósito. Pero este evento aumenta para cada cambio de carácter en EditText.

¿Que debería hacer?

 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 = 500; // 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 ); } } ); 

El truco está en cancelar y volver a programar Timer cada vez, cuando el texto en EditText consigue cambiado. ¡Buena suerte!

Utilice mejor el manejador con el método postDelayed (). En la implementación de Android, Timer creará un nuevo subproceso cada vez para ejecutar la tarea. Handler sin embargo tiene su propio Looper que se puede conectar a cualquier hilo que deseamos, por lo que no pagaremos un costo adicional para crear hilo.

Ejemplo

  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) { // } 

También puede utilizar la interfaz TextWatcher y crear su clase personalizada que lo implementa para volver a utilizar muchas veces su CustomTextWatcher y también puede pasar vistas o lo que sea necesario para su 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 

}

Ahora en tu actividad puedes usarlo así:

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

¿Cómo determinas que han terminado de escribir? ¿Que el edittext pierde el foco? Luego hay setOnFocusChangedListener .

Respuesta a la última edición en cuestión : Si desea esperar un tiempo específico después del último trazo de tecla, debe iniciar un hilo en la primera pulsación de tecla (use TextWatcher). Registre constantemente la hora de la última pulsación de tecla. Deje que el hilo duerma a la hora de la última pulsación de tecla + 0,5 segundos. Si la marca de tiempo de la última pulsación de tecla no se ha actualizado, haga lo que usted había previsto.

No de la solución anterior funcionó para mí.

Necesitaba una manera para que TextWatcher no se disparara en cada personaje que ingrese dentro de mi vista de búsqueda y muestre algún progreso, lo que significa que necesito acceder al subproceso de UI.

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

Eliminación de Handler en cada onTextChanged (que se llama cuando el usuario introduce un nuevo carácter). AfterTextChanged se llama después de que el texto se ha cambiado dentro del campo de entrada donde podemos iniciar el nuevo Runnable, pero lo cancelará si el usuario escribe más caracteres (Para más información, cuando se llamen estos llamados, vea esto ). Si el usuario no ingresa más caracteres, el intervalo pasará en postDelayed y llamará al trabajo que debe hacer con ese texto.

Este código se ejecutará sólo una vez por intervalo, no para cada entrada de usuario clave. Espero que ayude a alguien en el futuro.

Puede utilizar EditorActionListener para ese propósito.

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

Usar temporizador para su caso no es la mejor solución debido a la creación de nuevo objeto cada vez. De acuerdo con la documentación Timer ( http://developer.android.com/reference/java/util/Timer.html ) es mejor utilizar ScheduledThreadPoolExecutor –

"Los temporizadores programan tareas de un solo disparo o recurrentes para su ejecución. Prefieren ScheduledThreadPoolExecutor para el nuevo código."

Aquí hay un mejor enfoque

 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 } } ); 
  • Detectar retroceso en TextWatcher
  • EditText no se actualiza después de que se cambió el texto en TextWatcher
  • Cómo dar formato a la entrada de EditText al escribir con separadores de miles (,) en Android?
  • Android TextWatcher.afterTextChanged vs TextWatcher.onTextChanged
  • Android edittext onchange escucha
  • Cómo aplicar el evento de cambio de texto en EditText
  • ¿Cómo eliminar inmediatamente el espacio de un edittext si un usuario presiona el espacio?
  • Detectar cambios en EditText (TextWatcher ineficaz)
  • Validación de EditText con TextWatcher
  • Android - Hacer algo * después de * texto se cambia en EditText
  • Cómo cambiar TextView texto en DataChange sin llamada atrás TextWatcher Listener
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.