PDA

Ver la Versión Completa : listview automatica con thread


guti91
01/05/13, 20:26:00
buenas,
estoy buscando la manera para que los datos de una listview se actualicen automáticamente cuando cambien de valor.
Seria para que un valor de una acción en concreto cada vez que cambiara de precio se actualizara en un listview.
si alguien me pudiera explicar como hacerlo o algún ejemplo y así entenderlo

edit : los datos los recojo desde yahoo finance a partir de un csv que se tendría que bajar cada pocos segundos no? y actualizarlo estoy buscando información del AsyncTask no se si voy bien o no?

saludo y gracias.

kriogeN
01/05/13, 23:14:27
Esa sería una forma de hacerlo, en el onPostExecute del AsyncTask actualizas el Adapter del ListView (siempre y cuando hayan cambios).

En cuanto a la forma de hacer que se ejecute cada, por ejemplo, 5 segundos. La forma más rápida que se me ocurre es que en el onPostExecute al final vuelvas a crear otra vez el mismo AsyncTask, así se estaría llamando continuamente de forma "recursiva" (realmente sería iterativa, porque no se va acumulando en una pila, simplemente que uno llama a otro, pero el anterior termina). Y para controlar el tiempo, puedes hacerlo en el doInBackground, que lo primero que haga sea un Thread.sleep del tiempo que quieres que pase entre cada llamada.

Aunque es una forma un poco "sucia" de resolver el problema, pero por lo pronto para salir del paso te vale.

guti91
02/05/13, 13:24:29
vale muchas gracias voy a mirarlo merci:)
si tienes algún tutorial a mano de este tema me lo podrías pasar me harías un favor
saludos

guti91
06/05/13, 14:14:26
ya tengo el hilo hecho y funciona lo que no se como actualizar la listview por ejemplo cada 5 segundos o 20 segundos estoy probando con el timer pero la aplicación me peta alguien me puede echar una mano
gracias.

guti91
13/05/13, 14:00:58
solo he podido conseguir que se actualice cada vez que cambio de fragment y no se va borrando si no que se va poniendo debajo cada vez si alguien me puede echar una mano
porque si hago nombres.clear(que esta comentado) no me funciona si lo quito se va actualizando cada vez que cambio de fragment pero se va añadiendo a la arras...
algún consejo?

public class Fragment1 extends Fragment{

static List<String[]> datos = new ArrayList<String[]>();
static ListView lv;
static ArrayList nombres= new ArrayList();
static ArrayList valores= new ArrayList();

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){

View v= inflater.inflate(R.layout.fragment_1, container, false);
lv=(ListView)v.findViewById(R.id.listView1);
messageList();

return v;
}

private void messageList(){
adapter adapter = new adapter(getActivity(), null);
ArrayAdapter<String> adaptador = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, valores);
new MyLongTask().execute(adaptador);


for(int i=0;i<datos.size();i++){
for(int e=0;e<4;e++){
nombres.add(datos.get(i)[e]);
}
}
datos.clear();
valores=nombres;
System.out.println(valores);
//nombres.clear();

lv.setAdapter(adaptador);

}
static class MyLongTask extends AsyncTask<ArrayAdapter<String>, Void, Void> {


public MyLongTask(){}

@Override
protected void onPreExecute() {
// Avísele al usuario que estamos trabajando
}

@Override
protected Void doInBackground(ArrayAdapter<String>... params) {
String next[] = {};
List<String[]> list = new ArrayList<String[]>();
try {
URL url=new URL("http://finance.yahoo.com/d/quotes.csv?s=AAPL+GOOG+MSFT&f=nab2b3");
InputStreamReader in=new InputStreamReader(url.openStream());
CSVReader reader = new CSVReader(in);
for(;{
next = reader.readNext();
if(next != null){
list.add(next);

} else {
break;
}
}
datos=list;

} catch (IOException e) {
System.out.println(e);
}
try {
Thread.sleep(200);//2000 es 2 segundos
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}

protected void onPostExecute(ArrayAdapter<String> adaptador) {
new MyLongTask().execute();

adaptador.setNotifyOnChange(true);


}
}

}

saludos y muchas gracias

paquedo
13/05/13, 14:09:02
Yo tengo algo hecho para que me actualice los datos en pantalla cada 5 segundos (digamos que son contadores)

Te pongo las partes del código a ver si te sirve (mi información la saco de una Base de Datos en la propia aplicación):

private Handler mHandler = new Handler(); //variable global en la clase

//funcion que actualiza
private Runnable ActualizaPantalla = new Runnable()
{
public void run() {
loadDatos(); //este metodo se encarga de mostrar los datos en el listview
mHandler.removeCallbacks(ActualizaPantalla);
mHandler.postDelayed(this, 5000); //tiempo en milisegundos -> 5 segundos
}
};

en el método onPause
mHandler.removeCallbacks(ActualizaPantalla); //para que no consuma bateria mientras la aplicacion no está visible

en el metodo onResume
mHandler.removeCallbacks(ActualizaPantalla); //elimina la configuracion anterior
mHandler.postDelayed(ActualizaPantalla, 5000); //indica que se actualice cada 5 segundos

en el metodo onDestroy
mHandler.removeCallbacks(ActualizaPantalla);

kriogeN
13/05/13, 14:11:40
En todo caso esto:

adaptador.setNotifyOnChange(true);

Deberías ponerlo en el onPreExecute, ya que si lo pones en el onPostExecute las operaciones de inserción ya las has hecho, y no se va a llamar al notifyDataSetChanged.

Pero aún así, como las operaciones se hacen en un hilo que no es el UI no te lo recomiendo, es mejor que simplemente lo cambies por:

adaptador.notifyDataSetChanged();

EDITO: Y es más, mejor que inviertas el orden del onPostExecute y lo dejes así:

adaptador.notifyDataSetChanged();
new MyLongTask().execute();

El motivo es porque al revés es muy fácilmente que entres en exclusión mutua, y es tontería tener que empezar a poner semáforos cuando simplemente cambiando el orden resuelves el problema.

guti91
13/05/13, 17:23:53
kriogeN he puesto lo que me has dicho en el onpostexecute y me hace lo mismo que con como lo tenia osea se actualiza solo cuando cambio de fragment, si descomento la linea de nombres.clear() no hace nada...

paquedo estoy intentando hacerlo de la forma que tu lo has hecho pero no lo entiendo osea la funcion ActualizaPantalla se llama sola? yo es que creo que no me la llama lo unico que hecho ha sido quitar el loadDatos(); y he llamado a mi función messageList();donde he quitado new MyLongTask().execute(adaptador);

saludos y muchas gracias no encuentro como hacerlo no se si es problema de los fragments o que:S los estoy utilizando en el viewpagerindicator

paquedo
14/05/13, 00:16:08
La funcion ActualizaPantalla la llama el Handler cada 5000 milisegundos

Tal vez sea por estar usando fragments, yo la tengo puesta en una Activity normal que muestra un listview

guti91
15/05/13, 03:00:17
ya lo he conseguido lo dejo aqui por si alguien le sirve lo he hecho con el asynctask.

static class MyLongTask extends AsyncTask<String, Void, List<String[]>> {

protected void onPreExecute(ArrayAdapter<String> adaptador) {
// AvÌsele al usuario que estamos trabajando
}

@Override
protected List<String[]> doInBackground(String... params) {
String next[] = {};
List<String[]> list = new ArrayList<String[]>();
try {
URL url = new URL("http://finance.yahoo.com/d/quotes.csv?s=^GDAXI,^IXIC,^FCHI&f=nl1");

InputStreamReader in = new InputStreamReader(url.openStream());
CSVReader reader = new CSVReader(in);
for (;;) {
next = reader.readNext();
if (next != null) {
list.add(next);

} else {
break;
}
}

} catch (IOException e) {
System.out.println(e);
}

return list;
}

protected void onPostExecute(List<String[]> list) {
adaptador.clear();
for(int i = 0; i < list.size(); i++)
{
for (int e = 0; e < 1; e++) {
datos = new Listado(list.get(i)[0].toString(), list.get(i)[1].toString());
adaptador.add(datos);
}
}

adaptador.notifyDataSetChanged();
new MyLongTask().execute();
}
}