[Android] Actualizar un textbox cada X segundos con un thread

Buenos días,

estoy creando una aplicación, y para debugarla, me estoy limitando a que cada cierto tiempo me muestre en la UI la fecha y la hora, y ésta se refresque con un while de forma continua.

Mi código (resumido lo máximo) es el siguiente:

public class MainActivity extends Activity {

    private Random r = new Random();
    private int i1;
    private String fecha;
    private String valor;
    private Calendar c = Calendar.getInstance();
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private int seconds ;
    private TextView tv;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.logbox);
        new Thread(new Task()).start();

}

class Task implements Runnable {
        @Override
        public void run() {
            seconds = c.get(Calendar.SECOND);
            while (true){
                if ((seconds%15)==0) {
                    i1 = r.nextInt(80 - 1) + 1;
                    valor = Integer.toString(i1);
                    fecha = (sdf.format(c.getTime())).toString();
                    tv.setText("Fecha: " + fecha + "; Valor: " + valor);
                    seconds = c.get(Calendar.SECOND);
                }
            }

        }
    }


O sea, tv es mi cajita de texto. Y abro un nuevo hilo de la clase Task para que vaya haciendo en background el bucle de actualizar la fecha y mostrarla en la UI.

Pues por mucho que acorte el código, me devuelve miles de errores al lanzar la app (que no al compilar). El que más me llama la atención es éste:

E/NetworkScheduler.SchedulerReceiver﹕ Invalid package name : Perhaps you didn't include a PendingIntent in the extras?


¿alguna ayuda? ¿Puede que esté haciendo algún error garrafal?

Gracias!
El error ese que muestras no tiene nada que ver con el bucle.

Android tiene el denominado «UIThread», el único hilo que puede actualizar los elementos gráficos, si intentas actualizarlo desde cualquier otro «explota». Hay tres soluciones básicas: AsyncTask, Handler y runOnUiThread.

Si solo quieres hacer un debug rápido la última es la más fácil de implementar.

class Task implements Runnable {
        @Override
        public void run() {
            seconds = c.get(Calendar.SECOND);
            while (true){
                    i1 = r.nextInt(80 - 1) + 1;
                    valor = Integer.toString(i1);
                    fecha = (sdf.format(c.getTime())).toString();
                   runOnUiThread (new Thread(new Runnable() {
                       public void run() {
                               tv.setText("Fecha: " + fecha + "; Valor: " + valor);
                     }));
                    Thread.sleep(15*1000); //Esperamos 15 segundos en vez de tener un bucle a lo burro
                    seconds = c.get(Calendar.SECOND);                   
                }
        }
    }
a parte de lo que dice elchicosinhada, porque no usar Log?

Por otra parte si vas a trabajar con fechas te recomiendo JodaTime
Los nombres de variable me han dado cáncer [mad]

Consejo: Gasta algo de tiempo en pensar unos nombres de variables descriptivos (no importa que sean largos, para algo está el autocompletado), lo agradaceras.
@elchicosinhada: ¿y por qué salta el error? Antes lo tenía programado con un onClick y funcionaba. En todo caso, probaré lo que dices. Gracias.
@amchacon: ¿Qué les pasa a los nombres de las variables?
@nu_kru: "log", para qué? Probaré JodaTime.
banderas20 escribió:@amchacon: ¿Qué les pasa a los nombres de las variables?

Que no son descriptivos.

Por ejemplo:
private Random r = new Random();


¿r? Ese nombre no me dice nada del objeto. Es mejor:

private Random generador_de_aleatorios = new Random();


Este nombre es autodescriptivo y si lo veo en el código sabré perfectamente que es.

Otra ventaja que tiene esque es muy fácil de buscar, cosa que no pasa con la letra r.

banderas20 escribió:@nu_kru: "log", para qué? Probaré JodaTime.

Si conectas el movil por USB, todo lo que escribas en el log te sale en la consola del IDE. Me parece la forma más cómoda para depurar.
amchacon escribió:
banderas20 escribió:@amchacon: ¿Qué les pasa a los nombres de las variables?

Que no son descriptivos.

Por ejemplo:
private Random r = new Random();


¿r? Ese nombre no me dice nada del objeto. Es mejor:

private Random generador_de_aleatorios = new Random();


Este nombre es autodescriptivo y si lo veo en el código sabré perfectamente que es.

Otra ventaja que tiene esque es muy fácil de buscar, cosa que no pasa con la letra r.

banderas20 escribió:@nu_kru: "log", para qué? Probaré JodaTime.

Si conectas el movil por USB, todo lo que escribas en el log te sale en la consola del IDE. Me parece la forma más cómoda para depurar.


OK. La verdad es que los nombres me importan poco, porque es para probar la funcionalidad. Evidentemente, en una app seria lo haría con otros nombres.

Pues lo conecto por USB y ya me vomita todo el log por el IDE...
Hay que activar la depuración USB, instalar los drivers del fabricante y lanzar la aplicación desde el IDE... Tiene un poco de movida configurarlo la primera vez, pero creo que es la mejor forma de depurar.
amchacon escribió:Hay que activar la depuración USB, instalar los drivers del fabricante y lanzar la aplicación desde el IDE... Tiene un poco de movida configurarlo la primera vez, pero creo que es la mejor forma de depurar.


No, si lo que me refiero es que ya me sale por el IDE. Creo que ya lo tengo habilitado. [oki]
Yo por ejemplo usaria un Asynctask y en el onProgresUpdate haria que actualizara la fecha.
sodark escribió:Yo por ejemplo usaria un Asynctask y en el onProgresUpdate haria que actualizara la fecha.

[oki]
11 respuestas