Android – Actualizar ArrayAdapter a partir de un nuevo array

publicado por: Anonymous

necesito sabe como actualizar un ListView a partir de un ArrayAdapter propio por medio del array que le envio, me explico:
Tengo este JSON:

[{"id":"1","user":"117270122","mensaje":"Mensaje de prueba","condicion_visto":"0"},{"id":"2","user":"117270122","mensaje":"Mensaje","condicion_visto":"0"},{"id":"3","user":"117270122","mensaje":"Otro mensaje","condicion_visto":"0"}]  

El cual lo extraigo de la base de datos y lo convierto en un ArrayList aqui:

public ArrayList<String> fillArray(){
    final ArrayList<String> res = new ArrayList<String>();
    Thread th = new Thread(new Runnable() {
        @Override
        public void run() {
            try{
                JSONArray nodo = new JSONArray(db.verificarDatosNuevos(user));//El JSON lo extraigo de la base de datos
                for (int i = 0; i < nodo.length(); i++) {
                    JSONObject json = nodo.getJSONObject(i);
                    String usuario = json.getString("user");
                    String mensaje = json.getString("mensaje");
                    String output = "Para: " + usuario + "nMensaje: " + mensaje;
                    res.add(output);
                }
                System.out.println("NODO FINAL"+nodo.toString());
            }catch(Exception e){
                e.printStackTrace();
            }
            System.out.println("ARRAY FINAL"+res);
        }
    });
    th.start();
    try {
        th.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("ARRAY FINAL 2"+res);
    return res;
}  

Mas adelante lo llamo en el OnCreate:

Adaptador ad = new Adaptador(Principal.this,R.layout.lista_mensajes,list,a);
ListView lv = findViewById(R.id.listaMensajes);
lv.setAdapter(ad);  

El codigo de mi adaptador es el siguiente:

public class Adaptador extends ArrayAdapter<String>{
    ArrayList<String> arr;
    private TextView text;
    private String usuario = "";
    JsonParser j;
    public Adaptador(Context context, int textViewResourceId,ArrayList<String> objects,String c){
        super(context,textViewResourceId,objects);
        this.arr = objects;
        System.out.println("CONSTRUCTOR: "+arr.size());
        this.usuario = c;
        this.j = new JsonParser(usuario);
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        System.out.println("VIEW: "+arr.size());
        View view = null;
        LayoutInflater inflater = getLayoutInflater();
        view = inflater.inflate(R.layout.lista_mensajes,parent,false);
        TextView textView = view.findViewById(R.id.textoMensaje);
        textView.setText(arr.get(position));
        notifyDataSetChanged();
        return view;
    }

    public void actualizar(ArrayList<String> listaNueva){
        //this.arr.clear();
        this.arr = listaNueva;
        System.out.println("ACTUALIZAR: "+arr.toString());
        this.notifyDataSetChanged();
    }

}  

El problema es que en un boton cuando llamo a la funcion actualizar, no se actualiza:

btnref.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            list = j.fillArray();
            ad.notifyDataSetChanged();
            ad.actualizar(list);
        }
    });

Cuando la base de datos cambia, el json cambia, pero no sé como hacer para que el adaptador lo reconozca y cambie la lista, o si habrá alguna otra manera de actualizar la lista?

solución

Para poder actualizar la lista, no puedes notificar un cambio de referencia en memoria de la misma, sino, modificar sus elementos.

En pocas palabras no puedes hacer: this.lista = j.fillArray();

El Adapter es poblado con una referencia. Al ser iniciado no puede cambiar la referencia de dicha lista y por eso al llamar notifyDataSetChanged no pasa nada. Lo que debes hacer es modificar la que ya tienes, eliminando, agregando, limpiandola o insertando elementos en ella. Si quieres cambiar uno o todos los elementos se utiliza notifyDataSetChanged por lo que deberías modificar tu lista de la siguiente manera:

btnref.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            list.clear(); // Limpia la lista anterior
            list.addAll(j.fillArray()); // agrega los nuevos elementos
            ad.notifyDataSetChanged();
        }
    });

Basta con hacer eso para actualizar tu lista. Debes eliminar el método

public void actualizar(ArrayList<String> listaNueva){
        //this.arr.clear();
        this.arr = listaNueva;
        System.out.println("ACTUALIZAR: "+arr.toString());
        this.notifyDataSetChanged();
    }

y todas las demas llamadas a notifyDataSetChanged(); que no sea la del onClick.

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *