Autore Topic: ListView, eliminazione item, errore di procedimento, come fare?  (Letto 1198 volte)

Offline tune

  • Nuovo arrivato
  • *
  • Post: 18
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung S2
  • Sistema operativo:
    Win 8
0
CIao ragazzi,
sto impantanato dentro la + classica delle problematiche legate alla ListView: l'eliminazione.
ho letto tutto il materiale possibile, topic, tutorial su internet, ma niente.
cmq vi spiego brevemente la mia situazione, che non credo sia particolare ma assolutamente "usuale":

La mia ListView è un classico elenco di item(Note) a cui è associato ad ogni item due pulsanti "Delete/Edit".
Ora, il punto è che non ho grossi problemi nell'impostare i Listeners ai pulsanti etc etc, ma ho dei problemi di "concetto"...ovvero:

vorrei capire come è possibile associare ad ogni singolo pulsante l'ID dell'ITEM da eliminare/modificare?
ho usato il sistema offerto dall'uso di setTag(id) e getTag() e la cosa funziona.
soltanto che, da questo punto in poi, avendo l'ID dell'item e l'operazione da effettuare, non capisco come possa essere possibile eseguire l'operazione crud sql.

ecco il mio adapter, noterete che ora mi limito a stapare a video tramite un Toast l'id della nota selezionata, ma come faccio da questo punto ad andare ad eseguire effettivamente l'operazione?:
Codice (Java): [Seleziona]
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
               
                View row = null;
                final View delete;
                final View edit;
               
                //*** prima di tutto è necessario crearsi un oggetto inflater che
                //*** intrinsecamente associ il contesto attuale su cui si sta agendo
                //*** e il servizio che si è richiesto "layout_inflater"
                LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
               
                //*** una volta che ho l'oggetto inflater che associa contesto+servizio posso procedere
                //*** nell'identificazione dell'xml da usare
                row = inflater.inflate(R.layout.row, null );
               
                //*** una volta che ho la vista relativa al contesto attuale e relativa all'xml desiderato per layout
                //*** mi richiamo i propri elementi interni a cui associare i dati dell'oggetto item di turno
                TextView data           = (TextView)row.findViewById(R.id.item_data);
                TextView oggetto        = (TextView)row.findViewById(R.id.item_oggetto);
                delete  = (ImageButton)row.findViewById(R.id.button_row_delete);
                edit    = (ImageButton)row.findViewById(R.id.button_row_edit);
               
                //*** prende l'oggetto nell'array "Nota[] objects" passato in argomento
                //*** dato il proprio indice di posizione
                nota = getItem(position);
               
                //**** in fine associo agli appositi oggetti "TextView" i rispettivi valori
                data.setText(nota.get_dataInserimentoModifica());
                oggetto.setText(nota.get_oggetto());
               
                //*** poi associo i tag ai relativi pulsanti "Delete" e "Edit"
                delete.setTag(nota.get_id());
                edit.setTag(nota.get_id());
               
                //*** assegnazione dei listeners ai rispettivi pulsanti
                delete.setOnClickListener(crudListeners);
                edit.setOnClickListener(crudListeners);
               
                //*** inizializzo la variabile crudListeners che gestisce i listeners sui pulsanti
                crudListeners = new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                                int idnota = (Integer)v.getTag();
                                StringBuilder msg = new StringBuilder("ID nota ").append(idnota);
                                if(v.getId()==delete.getId()){
                                        msg.append(" DELETE");
                                }else{
                                        msg.append(" EDIT");
                                }
                                Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
                        }
                };             
               
                //*** torno la vista che finirà dentro "setAdapter()"
                return row;
        }

io pensavo nell'impostare un "redirect" ad un'activity che gestisse la cosa, ma ho notato che non è possibile perchè non sto in una activity,

insomma come si può eseguire questa semplice operazione?
Grazie in anticipo!
ps.se non vi è chiaro qualcosa chiedete pure...!

Offline tune

  • Nuovo arrivato
  • *
  • Post: 18
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung S2
  • Sistema operativo:
    Win 8
Re:ListView, eliminazione item, errore di procedimento, come fare?
« Risposta #1 il: 18 Marzo 2013, 11:48:57 CET »
0
Alla fine la parte di cancellazione l'ho interita direttamente dentro la classe che definisce il custom adapter:
Codice (Java): [Seleziona]
                                ...if(v.getId()==delete.getId()){
                                        //*** here, the item is deleted form the DB
                                        //*** but how is possible to refresh the list here?
                                        NotaCrud crud = new NotaCrud(getContext());
                                        Log.i(MainActivity.class.getName(), "Delete Nota, ID:"+idnota+" positionFinal:"+positionFinal);
                                        crud.deleteNota(idnota);
                                        listaNote.remove(positionFinal);
                                        notifyDataSetChanged();
                                }else{...

Soltanto che non si refresha la lista delle note, continuando a far vedere anche la nota appena cancellata, come potete vedere ho inserito "notifyDataSetChanged();" che dovrebbe fare al caso mio, ma il risultato è che non refresha.
com'è possibile refreshare dall'interno di questa classe la lista?

Grazie!

Offline lorux

  • Utente junior
  • **
  • Post: 97
  • Respect: +12
    • Google+
    • lor.catalano
    • Mostra profilo
  • Dispositivo Android:
    Galaxy S2
  • Sistema operativo:
    Windows
Re:ListView, eliminazione item, errore di procedimento, come fare?
« Risposta #2 il: 19 Marzo 2013, 13:03:52 CET »
0
Codice: [Seleziona]
listaNote.remove(positionFinal);
Il tuo Adapter estende ArrayAdapter<Nota>?
suppongo che sull'oncreate fai tipo
Codice: [Seleziona]
        public NotaAdapter(Context context, int textViewResourceId, List<Nota> note) {
                super(context, textViewResourceId, note);
                this.resource = textViewResourceId;
                 this.listanote = note;
        }

comunque dovresti passare come tag la postition dell'elemento(il primo argomento del getview) e non l'id.
Poi nell'onclick puoi fare Nota nota = getItem((Integer)v.getTag()); e una volta che hai la nota prendi il tuo id.
Dopo la delete fai remove(nota);

non credo proprio che la tua listanote e la lista interna all'adapter siano le stesse,quindi se fai listanote.remove(int) non stai modificando la lista dell'adapter.

In generale non serve che ti salvi un riferimento alla lista in un altro oggetto
« Ultima modifica: 19 Marzo 2013, 20:45:42 CET da lorux »

Offline tune

  • Nuovo arrivato
  • *
  • Post: 18
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung S2
  • Sistema operativo:
    Win 8
Re:ListView, eliminazione item, errore di procedimento, come fare?
« Risposta #3 il: 20 Marzo 2013, 10:09:09 CET »
0
Ciao, incollo tutto il mio adapter:
Codice (Java): [Seleziona]
package com.prendonota;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.TextView;
import com.prendonota.activeRecord.Nota;
import com.prendonota.crud.NotaCrud;

public class ListaNotaAdapter extends ArrayAdapter<Nota> {
       
        public Nota nota;
        public final List<Nota> listaNote;
        public final Activity activity;
       
        public ListaNotaAdapter(Context context, int textViewResourceId, List<Nota> objects) {
                super(context, textViewResourceId, objects);
                listaNote = objects;
                activity = (Activity)context;
        }              

       
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

                //*** queste final mi servono per esterne lo scope in modo
                //*** tale da renderle visibili in fase di definizione del listener            
                final View delete;
                final View edit;
                final int positionFinal;
                final Nota nota;
                final int idNota;
               
                LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.row, null );
               
                TextView data           = (TextView)convertView.findViewById(R.id.item_data);
                TextView oggetto        = (TextView)convertView.findViewById(R.id.item_oggetto);
                delete                          = (ImageButton)convertView.findViewById(R.id.button_row_delete);
                edit                                    = (ImageButton)convertView.findViewById(R.id.button_row_edit);
               
                nota            = getItem(position);
                idNota  = nota.get_id();
               
                //**** in fine associo agli appositi oggetti "TextView" i rispettivi valori della "nota di turno"
                data.setText(nota.get_dataInserimentoModifica());
                oggetto.setText( nota.get_oggetto());

                //*** assegno "position" alla costante per poterne leggere
                //*** il valore all'interno della definizione del listener
                positionFinal = position;
               
                //*** inizializzo la variabile crudListeners che gestisce i listeners sui pulsanti
                OnClickListener crudListeners = new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                                if(v.getId()==delete.getId()){
                                        NotaCrud crud = new NotaCrud(getContext());
                                        Log.i(MainActivity.class.getName(),
                                                        "Delete Nota, ID:" + idNota + " position on List(" + positionFinal +")" );
                                        crud.deleteNota(idNota);
                                        listaNote.remove(positionFinal);
                                        notifyDataSetChanged();
                                }else{
                                        Intent intent = new Intent(activity, EditNoteActivity.class);
                                        intent.putExtra(Constants.PN_EDIT_NOTE_OBJ, nota);
                                        activity.startActivity(intent);
                                }
                        }
                };

                //*** assegnazione dei listeners ai rispettivi pulsanti
                delete.setOnClickListener(crudListeners);
                edit.setOnClickListener(crudListeners);
               
                return convertView;
        }
}
come si può notare,ho dovuto usare delle costanti (listaNota, i vari pulsanti edit/delete e anche la position) per renderle visibili all'interno della definizione del listener.
e comunque, sì, è come dici te  @lorux, listaNote è la lista delle note che mi arriva come parametro e che gestisco all'interno del mio adapter tramite il costruttore, proprio come dicevi te.
ora così mi funziona tutto, l'aggiornamento e l'effettiva eleiminazione,
ma comunque penso che non sia il modo + "smart" per fare queto adapter[?]...

Offline lorux

  • Utente junior
  • **
  • Post: 97
  • Respect: +12
    • Google+
    • lor.catalano
    • Mostra profilo
  • Dispositivo Android:
    Galaxy S2
  • Sistema operativo:
    Windows
Re:ListView, eliminazione item, errore di procedimento, come fare?
« Risposta #4 il: 20 Marzo 2013, 10:40:43 CET »
+1
non mi piace che crei il listener DENTRO il getView,dovresti far implementare al tuo adapter l'OnClickListener e fare l'override del metodo onClick,sicuramente ne gioverai in prestazioni(creazione e scroll della lista + veloci).
Nel tuo modo,se hai 200 righe,stai creando 200 listener,il che è una cosa brutta e cattiva,visto che i pulsanti fanno tutti la stessa azione.

di seguito ho riscritto un pochino il tuo adapter e aggiunto dei commenti,guarda
Codice: [Seleziona]
package com.prendonota;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.TextView;
import com.prendonota.activeRecord.Nota;
import com.prendonota.crud.NotaCrud;

public class ListaNotaAdapter extends ArrayAdapter<Nota> implements OnClickListener{
       
        public Nota nota;
        //public final List<Nota> listaNote;
        public final Activity activity;
       
        public ListaNotaAdapter(Context context, int textViewResourceId, List<Nota> objects) {
                super(context, textViewResourceId, objects);
                //non tengo un riferimento alla lista
                                //listaNote = objects;
                activity = (Activity)context;
        }             

       
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

                //*** queste final mi servono per esterne lo scope in modo
                //*** tale da renderle visibili in fase di definizione del listener           
                final ImageButton delete;
                final ImageButton edit;
                final Nota nota;
               
                LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.row, null );
               
                TextView data           = (TextView)convertView.findViewById(R.id.item_data);
                TextView oggetto        = (TextView)convertView.findViewById(R.id.item_oggetto);
                delete                          = (ImageButton)convertView.findViewById(R.id.button_row_delete);
                edit                                    = (ImageButton)convertView.findViewById(R.id.button_row_edit);
               
                nota = getItem(position);
               
                //**** in fine associo agli appositi oggetti "TextView" i rispettivi valori della "nota di turno"
                data.setText(nota.get_dataInserimentoModifica());
                oggetto.setText( nota.get_oggetto());

                //ai bottoni metto this come listener
                delete.setOnClickListener(this);
                edit.setOnClickListener(this);
                               
               //aggiungo alla riga un tag con la posizione della view
                           //volendo puoi aggiungerlo direttamente al bottone
                            convertView.setTag(position);
                return convertView;
        }
               
                @Override
                public void onClick(View v) {
                                //prendo il parent(quindi la riga) e prendo il tag(la position) dalla quale mi ricavo la nota
                                Integer position = (Integer)arg0.getParent().getTag();
                                final Nota nota = getItem(position);
                                //al posto di delete.getId() puoi usare direttamente R.id.button_row_delete
                                //if(v.getId()==delete.getId()){
                                if(v.getId()==R.id.button_row_delete){
                                                NotaCrud crud = new NotaCrud(getContext());
                                                Log.i(MainActivity.class.getName(),
                                                                                "Delete Nota, ID:" + nota.get_id() + " position on List(" + position +")" );
                                                crud.deleteNota(idNota);
                                                listaNote.remove(nota);
                                                notifyDataSetChanged();
                                }else{
                                                Intent intent = new Intent(activity, EditNoteActivity.class);
                                                intent.putExtra(Constants.PN_EDIT_NOTE_OBJ, nota);
                                                activity.startActivity(intent);
                                }
                }
}

potrebbero esserci degli errori di compilazione perchè sto usando solo notepad++ XD

però come vedi,ora il listener è uno solo(l'adapter stesso) e,come ti avevo consigliato,nell'onclick ti serve solo la position della view cliccata per risalire alla nota,e la position la passo come tag alla convertView

Offline tune

  • Nuovo arrivato
  • *
  • Post: 18
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung S2
  • Sistema operativo:
    Win 8
Re:ListView, eliminazione item, errore di procedimento, come fare?
« Risposta #5 il: 20 Marzo 2013, 13:01:48 CET »
0
Prima di tutto Grazie.
ti posto il mio nuovo adapter dove ho seguito in parte le tue dritte, nei commenti troverai le motiazioni, se ti và di leggerlo...grazie in anticipo.
Codice (Java): [Seleziona]
...
//*** ho implementato l'iterfaccia, come mi hai suggerito
public class ListaNotaAdapter extends ArrayAdapter<Nota> implements OnClickListener{
       
        public Nota nota;
        public final Activity activity;
        //*** ho dovuto istaniare nuovamente la List altrimenti il remove(position) non funzionava
        public final List<Nota> listaNote;
        //*** ho istanziato i due pulsanti, perkè devo ancora capire
        //*** come usare bene l'interfaccia "ViewParent getparent()"
        //*** ad esempio ho notato che a "getTag()" non è definito per ViewParent
        //*** quindi di conseguenza il setTag l'ho fatto sui pulsanti
        private View delete;
        private View edit;
       
       
        public ListaNotaAdapter(Context context, int textViewResourceId, List<Nota> objects) {
                super(context, textViewResourceId, objects);
                activity = (Activity)context;
                listaNote = objects;
        }              
       
       
       
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
               
                LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.row, null );
               
                TextView data           = (TextView)convertView.findViewById(R.id.item_data);
                TextView oggetto        = (TextView)convertView.findViewById(R.id.item_oggetto);
                delete  = (ImageButton)convertView.findViewById(R.id.button_row_delete);
                edit    = (ImageButton)convertView.findViewById(R.id.button_row_edit);
               
                nota = getItem(position);
               
                //**** in fine associo agli appositi oggetti "TextView" i rispettivi valori
                data.setText(nota.get_dataInserimentoModifica());
                oggetto.setText( position + " - " + nota.get_id() + " - " + nota.get_oggetto());

                //*** assegnazione dei listeners ai rispettivi pulsanti
                delete.setOnClickListener(this);
                edit.setOnClickListener(this);

                //*** l'informazione della position la associo al pulsante delete
                //*** perchè devo capire ancora bene la strada per usare ViewParent
                delete.setTag(position);
                edit.setTag(position);
               
                return convertView;
        }

       
                @Override
                public void onClick(View v) {
                       
                        //*** come prima istruzione del listener prendo la position
                        //*** salvata precedentemente col "setTag" sui singoli pulsanti
                        int position = (Integer)v.getTag();
                        Nota nota = getItem(position);

                        Log.i(MainActivity.class.getName(),
                                        "onClick, ID:" + nota.get_id() + " position on list(" + position +")" );
                       
                        if(v.getId()==R.id.button_row_delete){
                                NotaCrud crud = new NotaCrud(getContext());
                                Log.i(MainActivity.class.getName(),
                                                "Delete Nota, ID:" + nota.get_id() + " position on list(" + position +")" );
                                crud.deleteNota(nota.get_id());
                                //*** "listaNote" non avevo modo di eliminare l'item selezionato
                                //*** se hai un consiglio su come avrei potuto procedere in questo punto te ne sarei ulteriormente grato!
                                listaNote.remove(position);
                                notifyDataSetChanged();
                        }else{
                                Intent intent = new Intent(activity, EditNoteActivity.class);
                                intent.putExtra(Constants.PN_EDIT_NOTE_OBJ, nota);
                                activity.startActivity(intent);
                        }
        };     
}

in queto modo non dovrei creare "200" oggetti no?

Offline lorux

  • Utente junior
  • **
  • Post: 97
  • Respect: +12
    • Google+
    • lor.catalano
    • Mostra profilo
  • Dispositivo Android:
    Galaxy S2
  • Sistema operativo:
    Windows
Re:ListView, eliminazione item, errore di procedimento, come fare?
« Risposta #6 il: 20 Marzo 2013, 13:18:55 CET »
+1
ok ho fatto un paio di errori  :-P

ViewParent come dici tu non ha getTag,ti basta fare View parent = (View) v.getParent(); per avere la riga cliccata,ma vabbè a usare il tag nel button non cambia nulla.

Sicuro che poi al posto di listaNote.remove(position); non puoi usare direttamente remove(nota)?(nel codice che avevo scritto prima ho dimenticato di cambiarlo)

Codice: [Seleziona]
if(v.getId()==R.id.button_row_delete){
                                NotaCrud crud = new NotaCrud(getContext());
                                Log.i(MainActivity.class.getName(),
                                                "Delete Nota, ID:" + nota.get_id() + " position on list(" + position +")" );
                                crud.deleteNota(nota.get_id());
                                //*** "listaNote" non avevo modo di eliminare l'item selezionato
                                //*** se hai un consiglio su come avrei potuto procedere in questo punto te ne sarei ulteriormente grato!
                                remove(nota);
                                notifyDataSetChanged();
                        }

in teoria poi gli adapter hanno di default a true un flag che sulle modifiche alla lista  (add(T), insert(T, int), remove(T), clear()) fà automaticamente il notifyDataSetChanged,quindi non servirebbe neanche chiamare quello,ma vabbè per sicurezza lascialo,se poi funziona puoi provare a toglierlo e vedere se va ancora
« Ultima modifica: 20 Marzo 2013, 13:23:18 CET da lorux »

Offline tune

  • Nuovo arrivato
  • *
  • Post: 18
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung S2
  • Sistema operativo:
    Win 8
Re:ListView, eliminazione item, errore di procedimento, come fare?
« Risposta #7 il: 20 Marzo 2013, 13:51:12 CET »
0
 :-) ok, allora:
funziona li "remove" secco sull'ArrayAdapter, quindi questa cosa mi ha permesso di eliminare la variabile "listaNote": OK.
funziona pure il refresh automatico, come dicevi te, quindi ho tolto "notifyDataSetChanged": OK.

Per completezza riposto nuovamente il mio adapter aggiornato, così funziona...Grazie Ancora!
Codice (Java): [Seleziona]
package com.prendonota;

import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.TextView;

import com.prendonota.activeRecord.Nota;
import com.prendonota.crud.NotaCrud;

public class ListaNotaAdapter extends ArrayAdapter<Nota> implements OnClickListener{
       
        public Nota nota;
        public final Activity activity;
        private View delete;
        private View edit;
       
        public ListaNotaAdapter(Context context, int textViewResourceId, List<Nota> objects) {
                super(context, textViewResourceId, objects);
                activity = (Activity)context;
        }              
       
       
       
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
               
                LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.row, null );
               
                TextView data           = (TextView)convertView.findViewById(R.id.item_data);
                TextView oggetto        = (TextView)convertView.findViewById(R.id.item_oggetto);
                delete  = (ImageButton)convertView.findViewById(R.id.button_row_delete);
                edit    = (ImageButton)convertView.findViewById(R.id.button_row_edit);
               
                nota = getItem(position);
               
                //**** in fine associo agli appositi oggetti "TextView" i rispettivi valori
                data.setText(nota.get_dataInserimentoModifica());
                oggetto.setText( position + " - " + nota.get_id() + " - " + nota.get_oggetto());

                //*** assegnazione dei listeners ai rispettivi pulsanti
                delete.setOnClickListener(this);
                edit.setOnClickListener(this);

                //*** l'informazione della position la associo al pulsante delete
                //*** perchè devo capire ancora bene la strada per usare ViewParent
                delete.setTag(position);
                edit.setTag(position);
               
                return convertView;
        }

       
                @Override
                public void onClick(View v) {
                       
                        //*** come prima istruzione del listener prendo la position
                        //*** salvata precedentemente col "setTag"
                        int position = (Integer)v.getTag();
                       
                        Nota nota = getItem(position);

                        Log.i(MainActivity.class.getName(),
                                        "onClick, ID:" + nota.get_id() + " position on list(" + position +")" );
                       
                        if(v.getId()==R.id.button_row_delete){
                                NotaCrud crud = new NotaCrud(getContext());
                                Log.i(MainActivity.class.getName(),
                                                "Delete Nota, ID:" + nota.get_id() + " position on list(" + position +")" );
                                crud.deleteNota(nota.get_id());
                                this.remove(nota);
                        }else{
                                Intent intent = new Intent(activity, EditNoteActivity.class);
                                intent.putExtra(Constants.PN_EDIT_NOTE_OBJ, nota);
                                activity.startActivity(intent);
                        }
        };     
       
}

Grazie e alla prossima magari!