2011-07-14 7 views
42

Estoy usando un temporizador para crear un cronómetro. El temporizador funciona aumentando un valor entero. Quiero mostrar este valor en la actividad al actualizar constantemente una vista de texto.Temporizador Android actualizando una vista de texto (IU)

Aquí está mi código del servicio donde trato y actualizar de Vista de Texto de la actividad:

protected static void startTimer() { 
    isTimerRunning = true; 
    timer.scheduleAtFixedRate(new TimerTask() { 
     public void run() { 
      elapsedTime += 1; //increase every sec 
      StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview 
     } 
    }, 0, 1000); 
} 

Tengo algún tipo de error acerca de la actualización de la interfaz de usuario en el hilo equivocado.

¿Cómo puedo adaptar mi código para realizar esta tarea de actualización constante de la vista de texto?

+0

No estoy familiarizado con la api andriod, pero puede que tenga que llamar manualmente a repintado() o cualquier método que use cuando actualice la constancia del campo de texto. –

Respuesta

84
protected static void startTimer() { 
    isTimerRunning = true; 
    timer.scheduleAtFixedRate(new TimerTask() { 
     public void run() { 
      elapsedTime += 1; //increase every sec 
      mHandler.obtainMessage(1).sendToTarget(); 
     } 
    }, 0, 1000); 
} 

public Handler mHandler = new Handler() { 
    public void handleMessage(Message msg) { 
     StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview 
    } 
}; 

Por encima de código funcionará ...

Nota: Los manipuladores deben crearse en el hilo principal para que pueda modificar el contenido de la interfaz de usuario.

+1

gracias, esta es la solución que implementaré – JDS

+0

Lo más bienvenido..bro. – Nirav

+0

Buena solución simple. Sin embargo, una corrección: la llave final "}" que completa la definición de su controlador requiere un ";" –

2

TimerTask implementa Runnable, que lo convertiría en un hilo. No puede actualizar el hilo principal de la interfaz de usuario directamente desde un hilo diferente sin algún trabajo. Una cosa que podría hacer es usar Async Task para crear el temporizador y publicar una actualización cada segundo que actualizará la UI.

2

Supongo que StopWatch.time es una referencia estática o pública a su TextView. En lugar de hacer esto, debe implementar un BroadcastReceiver para comunicarse entre su temporizador (que se ejecuta desde un hilo separado) y su TextView.

8

En su lugar, debe usar Handler para actualizar la IU cada X segundos. Aquí hay otra pregunta que muestra un ejemplo: Repeat a task with a time delay?

Su enfoque no funciona porque está tratando de actualizar la interfaz de usuario desde el subproceso no relacionado con la interfaz de usuario. Esto no esta permitido.

6
StopWatch.time.post(new Runnable() { 
    StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); 
}); 

este bloque de código se basa en el controlador pero no es necesario crear su propia instancia de controlador.

+25

Nota para lectores futuros: no existe una clase incorporada "Cronómetro" en Android; esta respuesta se refiere al ejemplo de código de OP, en el que "Cronómetro" es el nombre del TextView del OP. – ToolmakerSteve

2

Usted puede utilizar la siguiente utilidad:

/** 
* Created by Ofek on 19/08/2015. 
*/ 
public class TaskScheduler extends Handler { 
    private ArrayMap<Runnable,Runnable> tasks = new ArrayMap<>(); 
    public void scheduleAtFixedRate(final Runnable task,long delay,final long period) { 
     Runnable runnable = new Runnable() { 
      @Override 
      public void run() { 
       task.run(); 
       postDelayed(this, period); 
      } 
     }; 
     tasks.put(task, runnable); 
     postDelayed(runnable, delay); 
    } 
    public void scheduleAtFixedRate(final Runnable task,final long period) { 
     Runnable runnable = new Runnable() { 
      @Override 
      public void run() { 
       task.run(); 
       postDelayed(this, period); 
      } 
     }; 
     tasks.put(task, runnable); 
     runnable.run(); 
    } 
    public void stop(Runnable task) { 
     Runnable removed = tasks.remove(task); 
     if (removed!=null) removeCallbacks(removed); 
    } 

} 

A continuación, en cualquier lugar en el código que se ejecuta por el hilo de interfaz de usuario que se puede utilizar simplemente como esto:

TaskScheduler timer = new TaskScheduler(); 
     timer.scheduleAtFixedRate(new Runnable() { 
      @Override 
      public void run() { 
       time.setText(simpleDateFormat.format(GamePlay.instance().getLevelTime())); 
      } 
     },1000); 
-3
timer.schedule(new TimerTask() { 
      @Override 
      public void run() { 

       //your actions 

      } 
     },1*1000);//1 sec 
1

puede utilizar Handler.

este código incremento de un contador cada segundo y espectáculo y actualizar valor del contador en una TextView.

public class MainActivity extends Activity { 


    private Handler handler = new Handler(); 
    private TextView textView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     textView = (TextView) findViewById(R.id.text); 
     startTimer(); 
    } 


    int i = 0; 
    Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 
      i++; 
      textView.setText("counter:" + i); 
      startTimer(); 
     } 
    }; 

    public void startTimer() { 
     handler.postDelayed(runnable, 1000); 
    } 

    public void cancelTimer() { 
     handler.removeCallbacks(runnable); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     handler.removeCallbacks(runnable); 
    } 
} 
Cuestiones relacionadas