Ver la Versión Completa : Duda delay en bucle
joselugf
02/11/16, 20:37:26
Buenas he empezado hace poco con android, estoy intentando hacer un pequeño album de fotos apartir de un array. Lo que quiero es mostrar a partir de un ImageView una imagen del array cada 5 segundos pero no logro conseguirlo, he intentado utilizar el SystemClock.sleep() pero no me funciona, supongo que lo hago de una forma erronea, dejo mi codigo para que alguien pueda modificarlo y ayudarme. Gracias
import android.content.res.TypedArray;
import android.media.Image;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import java.util.logging.Handler;
public class MainActivity extends AppCompatActivity {
private ImageView img;
private TypedArray fotos;
private int numFoto = 0;
private Thread temporizador;
override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img = (ImageView) findViewById(R.id.imagen);
cargarArray();
albumFotos();
}
public void cargarArray() {
fotos = getResources().obtainTypedArray(R.array.fotos);
}
public void albumFotos() {
while(numFoto < 4){
numFoto++;
img.setImageDrawable(fotos.getDrawable(numFoto));
SystemClock.sleep(5000);
}
}
}
kriogeN
03/11/16, 08:34:50
La espera tienes que hacerla en segundo plano, de lo contrario el método no terminará y no se ejecutará el método onDraw que pinta en la pantalla.
Es decir, hasta que no termina el código de esperar 5 segundos x 4 fotos = 20 segundos no pintará la imagen, que por supuesto será sólo la última foto.
Tu método "albumFotos" debería ser un AsyncTask, que en su doInBackground haga el bucle y la espera, y en su oProgressUpdate establezca la imagen.
Algo así:
protected void doInBackground() {
while(numFoto < 4){
numFoto++;
publishProgress(numFoto)
SystemClock.sleep(5000);
}
}
protected void onProgressUpdate(Integer... progress) {
img.setImageDrawable(fotos.getDrawable(progress[0]));
}
mocelet
03/11/16, 10:27:09
El ejemplo que te ha dado kriogeN es justo cómo harías lo que estás haciendo (bucle con espera) sin bloquear el sistema.
Para este caso particular que solo quieres ejecutar una cosa cuando pase cierto tiempo hay más mecanismos, como el postDelayed que tiene cualquier View o mejor todavía un Handler que te da más control. Le pasas un Runnable con lo que quieras que haga y el tiempo en el que quieres que lo ejecute. Es más ligero que un AsyncTask, te ahorras crear un hilo de ejecución y tenerlo bloqueado con sleep y sabes que siempre estás ejecutando el código en el hilo principal.
joselugf
03/11/16, 10:57:39
Gracias por contestar! aun así me sigue costando mucho entender en que casos utilizarse cada tipo de hilo, también leí por ahí que se pueden hacer/modificar los servicios en ve de hilos, no se si entendí bien, es cierto?
mocelet
03/11/16, 11:36:33
A grandes rasgos solo hay dos tipos de hilos, el hilo principal y todos los demás.
Cuando escribes un programa se va ejecutando una línea detrás de otra, eso es un hilo, una secuencia de órdenes. Hasta que no acaba la orden anterior no se pone con la siguiente.
En Android existe un hilo llamado hilo principal que es el que se encarga de ver si el usuario ha tocado la pantalla, dónde, avisar a la app para que responda y llamar a tus métodos onXXX cuando corresponda, pintar la pantalla con los cambios y volver a ver si el usuario hizo algo. Todo esto unas 60 veces por segundo para que el sistema sea fluido. Como un juego... También se le llama UI Thread precisamente porque es el que gestiona la interfaz de usuario.
El resto de hilos los creas cuando necesitas ejecutar una secuencia de código que dura mucho tiempo y dejaría bloqueado a Android que no podría hacer su trabajo en el hilo principal (por ejemplo un sleep, una conexión a un servidor, procesar una imagen, etc.).
Si quieres más información hay mucho material en las redes. Aquí mismamente: http://www.sgoliver.net/blog/tareas-en-segundo-plano-en-android-i-thread-y-asynctask/
joselugf
03/11/16, 12:55:31
Finalmente lo he conseguido con la solucion que me dieron. Lo he hecho así
public class MainActivity extends AppCompatActivity {
private ImageView img;
private TypedArray fotos;
private int numFoto = 0;
override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img = (ImageView) findViewById(R.id.imagen);
cargarArray();
pasaFotos();
}
public void cargarArray() {
fotos = getResources().obtainTypedArray(R.array.fotos);
}
public void pasaFotos(){
FotosAleatorias fotosAle = new FotosAleatorias();
fotosAle.execute();
}
private class FotosAleatorias extends AsyncTask<Void, Integer, Void> {
override
protected Void doInBackground(Void... params) {
while (numFoto < 4) {
publishProgress(numFoto);
numFoto++;
SystemClock.sleep(5000);
}
return null;
}
override
protected void onProgressUpdate(Integer... values) {
img.setImageDrawable(fotos.getDrawable(values[0]));
}
}
}
Aunque no se si es la forma "correcta" ya que he hecho la clase que extiende de AsincTask dentro del main y no se si sería mas conveniente en hacerlo en una clase nueva aparte??.
mocelet
03/11/16, 14:47:14
Aunque no se si es la forma "correcta" ya que he hecho la clase que extiende de AsincTask dentro del main y no se si sería mas conveniente en hacerlo en una clase nueva aparte??.
Si la sacas fuera no podrás acceder a numFotos ni a ninguna variable porque son privadas, así que tiene que estar dentro. De hecho hasta podrías haber creado una clase interna (inner class), al fin y al cabo no estás añadiendo métodos nuevos y no es un código que vayas a utilizar en otros sitios más que en el pasarFotos.
AsyncTask fotosAle = new AsyncTask<Void, Integer, Void>() {
/* el doInBackground y el onProgressUpdate igual */
};
fotosAle.execute();
vBulletin® v3.8.1, Copyright ©2000-2025, Jelsoft Enterprises Ltd.