Autore Topic: notifyDataSetChanged() Mi sta facendo impazzire.  (Letto 565 volte)

Offline lcisetti

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Windows 7
notifyDataSetChanged() Mi sta facendo impazzire.
« il: 19 Aprile 2016, 13:41:36 CEST »
0
Salve a tutti.

Chiedo un aiuto per capire cosa mi stia sfuggendo.

La MainActivity:
Codice: [Seleziona]

public class MainActivity extends AppCompatActivity {

    private ProvinceAdapter dbProvince;
    private Cursor cursor;

    ProvinceCustomAdapter provinciaAdapter;
    ArrayList<Provincia> userArray = new ArrayList<Provincia>();


    Button addprovincia_bt;
    ListView lv;

    TextView id_provincia, codice_provincia, nome_provincia;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        addprovincia_bt = (Button) findViewById(R.id.button_add_Provincia);

        addprovincia_bt.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent add_mem = new Intent(MainActivity.this, AddMemberActivity.class);
                startActivity(add_mem);
            }
        });


        try {

            dbProvince = new ProvinceAdapter(this);

            dbProvince.open();
         
            ArrayList<Provincia> q = dbProvince.getProvinceArrayList();
           
            provinciaAdapter = new ProvinceCustomAdapter(MainActivity.this, R.layout.province_listview_row, q);
            lv = (ListView) findViewById(R.id.listViewProvince);
            lv.setItemsCanFocus(false);
            lv.setAdapter(provinciaAdapter);
           
            lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                @Override
                public void onItemClick(AdapterView<?> parent, View v,
                                        final int position, long id) {
                      Toast.makeText(MainActivity.this, "List View Clicked:" + position, Toast.LENGTH_LONG).show();
                }
            });
         
        } catch (Exception e) {
           
        }

    }
}


L'Adapter per gestire le operazioni sulla tabella

Codice: [Seleziona]

public class ProvinceAdapter {

    @SuppressWarnings("unused")
    private static final String LOG_TAG = ProvinceAdapter.class.getSimpleName();

    private Context context;
    private SQLiteDatabase database;
    private DatabaseHelper dbHelper;

    // Database fields
    private static final String DATABASE_TABLE      = "province";

    public static final String KEY_ID     = "_id";
    public static final String KEY_CODICE = "codice";
    public static final String KEY_NOME   = "nome";


    static ArrayList<Provincia> gs;


    public ProvinceAdapter(Context context) {
        this.context = context;
    }

    public ProvinceAdapter open() throws SQLException {
        dbHelper = new DatabaseHelper(context);
        database = dbHelper.getWritableDatabase();
        return this;
    }

    public void close() {
        dbHelper.close();
    }

    private ContentValues createContentValues(String codice, String nome ) {
        ContentValues values = new ContentValues();
        values.put( KEY_CODICE, codice );
        values.put(KEY_NOME, nome);

        return values;
    }

    //create a record
    public long createProvincia(String codice, String nome ) {
        ContentValues initialValues = createContentValues(codice, nome);
        return database.insertOrThrow(DATABASE_TABLE, null, initialValues);
    }

    //update a record
    public boolean updateProvincia( long ID, String codice, String nome ) {
        ContentValues updateValues = createContentValues(codice, nome);
        return database.update(DATABASE_TABLE, updateValues, KEY_ID + "=" + ID, null) > 0;
    }

    //delete a record
    public void deleteProvincia(long ID) {
        database.delete(DATABASE_TABLE, KEY_ID + "=" + ID, null);
    }

   public Cursor fetchAllProvince() {
        String[] columns = new String[] { KEY_ID, KEY_CODICE, KEY_NOME };
        Cursor cursor = database.query(DATABASE_TABLE, columns, null, null, null, null, null);
        if (cursor != null) {
            cursor.moveToFirst();
        }
        return cursor;
    }


    public ArrayList<Provincia> getProvinceArrayList() {
        try{
            Cursor c1 = database.rawQuery("SELECT * FROM " + DATABASE_TABLE, null);
            gs = new ArrayList<Provincia>();
            while (c1.moveToNext())
            {
                Provincia q1 = new Provincia();

                q1.setID(c1.getString(0));
                q1.setCodice(c1.getString(1));
                q1.setNome(c1.getString(2));

                gs.add(q1);

            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return gs;
    }

    //fetch records filter by a string
    public Cursor fetchProvinceByFilter(String filter) {
        Cursor mCursor = database.query(true, DATABASE_TABLE, new String[] {
                        KEY_ID, KEY_CODICE, KEY_NOME },
                KEY_NOME + " like '%"+ filter + "%'", null, null, null, null, null);

        return mCursor;
    }

}



Il Model
Codice: [Seleziona]

public class Provincia {
    String ID;
    String codice;
    String nome;

    public String getID() {
        return ID;
    }

    public void setID(String ID) {
        this.ID = ID;
    }

    public String getCodice() {
        return codice;
    }

    public void setCodice(String codice) {
        this.codice = codice;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public Provincia() {

    }

    public Provincia(String ID, String codice, String nome) {
        super();
        this.ID = ID;
        this.codice = codice;
        this.nome = nome;
    }

}



Il CustomAdapter

Codice: [Seleziona]

public class ProvinceCustomAdapter extends ArrayAdapter<Provincia> {
    Context context;
    int layoutResourceId;
    ArrayList<Provincia> data = new ArrayList<Provincia>();

    private ProvinceAdapter dbProvince;

    public ProvinceCustomAdapter(Context context, int layoutResourceId, ArrayList<Provincia> data) {
        super(context, layoutResourceId, data);
        this.layoutResourceId = layoutResourceId;
        this.context = context;
        this.data = data;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        ProvinciaHolder holder = null;

        if (row == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);
            holder = new ProvinciaHolder();
            holder.textID = (TextView) row.findViewById(R.id.provincia_id);
            holder.textCodice = (TextView) row.findViewById(R.id.provincia_codice);
            holder.textNome = (TextView) row.findViewById(R.id.provincia_nome);
            holder.btnEdit = (Button) row.findViewById(R.id.button1);
            holder.btnDelete = (Button) row.findViewById(R.id.button2);
            row.setTag(holder);
        } else {
            holder = (ProvinciaHolder) row.getTag();
        }
        final Provincia prov = data.get(position);
        holder.textID.setText(prov.getID());
        holder.textCodice.setText(prov.getCodice());
        holder.textNome.setText(prov.getNome());
        holder.btnEdit.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                Toast.makeText(context, "Edit button Clicked " + prov.getID(), Toast.LENGTH_LONG).show();

                Intent modify_intent = new Intent(context, ModifyMemberActivity.class);
                modify_intent.putExtra("memberID", prov.getID());
                modify_intent.putExtra("memberCodice", prov.getCodice());
                modify_intent.putExtra("memberName", prov.getNome());

                context.startActivity(modify_intent);

            }
        });
        holder.btnDelete.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Toast.makeText(context, "Delete button Clicked " + prov.getID(), Toast.LENGTH_LONG).show();

                dbProvince = new ProvinceAdapter(context);
                dbProvince.deleteProvincia(Long.parseLong(prov.getID()));
                notifyDataSetChanged();    [b][color=red]-------->> IL PROBLEMA E' QUI (LA LISTVIEW NON SI AGGIORNA)[/color][/b]
            }
        });
        return row;

    }

    static class ProvinciaHolder {
        TextView textID;
        TextView textCodice;
        TextView textNome;
        Button btnEdit;
        Button btnDelete;
    }
}




In breve, funziona tutto tranne il refresh della listview dopo la cancellazione della provincia nel Custom Adapter.

##############
dbProvince = new ProvinceAdapter(context);
dbProvince.deleteProvincia(Long.parseLong(prov.getID()));
notifyDataSetChanged();    -------->> IL PROBLEMA E' QUI (LA LISTVIEW NON SI AGGIORNA)
##############


Grazie

Luca
« Ultima modifica: 19 Aprile 2016, 13:52:47 CEST da lcisetti »

Offline tonno16

  • Utente storico
  • *****
  • Post: 1169
  • Respect: +56
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:notifyDataSetChanged() Mi sta facendo impazzire.
« Risposta #1 il: 19 Aprile 2016, 14:53:21 CEST »
0
Hai una classe adapter che non estende niente. Devo estendere cursorAdapter o ArrayAdapter.

Offline lcisetti

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Windows 7
Re:notifyDataSetChanged() Mi sta facendo impazzire.
« Risposta #2 il: 19 Aprile 2016, 16:57:49 CEST »
0
Ti ringrazio per la risposta tonno.

Mi faresti una grande cortesia dandomi qualche indizio in più. Sono alle prime armi con Android.

Luca

Offline tonno16

  • Utente storico
  • *****
  • Post: 1169
  • Respect: +56
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:notifyDataSetChanged() Mi sta facendo impazzire.
« Risposta #3 il: 19 Aprile 2016, 19:15:00 CEST »
0
ProvincieAdapter è una classe che non estende niente

Offline lcisetti

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Windows 7
Re:notifyDataSetChanged() Mi sta facendo impazzire.
« Risposta #4 il: 19 Aprile 2016, 21:25:31 CEST »
0
Ti ringrazio ancora ma da solo non ci arrivo.

Offline tonno16

  • Utente storico
  • *****
  • Post: 1169
  • Respect: +56
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:notifyDataSetChanged() Mi sta facendo impazzire.
« Risposta #5 il: 20 Aprile 2016, 00:58:43 CEST »
0
Se usi dati SQLite allora non dovresti usare ArrayAdapter. Ma dovresti usare CursorAdapter. Gli ArrayAdapter servono per le liste. I cursor adapter per i cursor. Nel tuo caso se ti appoggi ad un ArrayAdapter una volta che elimini un record da DB devi anche rimuovere l'elemento dalla lista ovvero da userArray. E poi chiamare notifyDataSetChanged()

Offline pietroconti89

  • Utente normale
  • ***
  • Post: 164
  • Respect: +19
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Note 3 N9005
  • Sistema operativo:
    Windows / Mac OSX
Re:notifyDataSetChanged() Mi sta facendo impazzire.
« Risposta #6 il: 20 Aprile 2016, 12:48:58 CEST »
0
Codice (Java): [Seleziona]
holder.btnDelete.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Toast.makeText(context, "Delete button Clicked " + prov.getID(), Toast.LENGTH_LONG).show();

                dbProvince = new ProvinceAdapter(context);
                dbProvince.deleteProvincia(Long.parseLong(prov.getID()));
                notifyDataSetChanged();    [b][color=red]-------->> IL PROBLEMA E' QUI (LA LISTVIEW NON SI AGGIORNA)[/color][/b]
            }
        });


prova cosi

Codice (Java): [Seleziona]
holder.btnDelete.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Toast.makeText(context, "Delete button Clicked " + prov.getID(), Toast.LENGTH_LONG).show();

                dbProvince = new ProvinceAdapter(context);
                dbProvince.deleteProvincia(Long.parseLong(prov.getID()));
                data.remove(position);
                notifyDataSetChanged();    [b][color=red]-------->> IL PROBLEMA E' QUI (LA LISTVIEW NON SI AGGIORNA)[/color][/b]
            }
        });


Post unito: 20 Aprile 2016, 13:02:44 CEST
comunque per chiarezza , il notifyDataSetChanged(); non ha nulla a che vedere con la parte SQL , o meglio una volta che la listview viene caricata , non importa se i dati sono presenti o no nel DB , alla listview interessano solo gli iTem che vengono caricati con l'arrayadapter ,
Codice (Java): [Seleziona]
public class ProvinceCustomAdapter extends ArrayAdapter<Provincia>
in particolare questi
Codice (Java): [Seleziona]
 this.data = data;
li sono presenti tutti gli item della listview , quindi se vuoi che una riga della listview venga tolta , devi semplicemente eliminarla dall arraylist con la funzione arraylist.remove(posizione elemento )

ovviamente il tuo scopo presumo sia , sia quello di eliminare la riga sia quello di eliminare l'elemento dal DB , per far questo io la penserei cosi....
tento l' eliminazione dell elemento dal DB ... se essa va a buon fine allora rimuovo l'item corrispondente dall arrayadapter e notifico alla listview che l'adapter è cambiato , a questo punto punto verrà aggiornato il tutto eliminando le righe interessate

saluti
« Ultima modifica: 20 Aprile 2016, 13:02:44 CEST da pietroconti89, Reason: Merged DoublePost »

Offline lcisetti

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Windows 7
Re:notifyDataSetChanged() Mi sta facendo impazzire.
« Risposta #7 il: 20 Aprile 2016, 18:43:31 CEST »
0
Grazie Pietro Conti.

E' bastato aggiungere la tua riga "data.remove(position);" è il tutto ha funzionato magicamente.

Grande veramente !

Grazie infinite.

P.S.
Siccome è il mio primo progetto Android ho tanta confusione e approfitto ancora per chiederti di suggerirmi qual è il metodo migliore per gestire operazioni CRUD, soprattutto in virtù di un utilizzo massiccio con le ListView.

Grazie ancora.

Offline pietroconti89

  • Utente normale
  • ***
  • Post: 164
  • Respect: +19
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Note 3 N9005
  • Sistema operativo:
    Windows / Mac OSX
Re:notifyDataSetChanged() Mi sta facendo impazzire.
« Risposta #8 il: 20 Aprile 2016, 20:00:48 CEST »
0
sai android e grandi volumi di dati non lega molto , però si può ottimizzare il tutto , ad esempio implementerei le chiamate e l'inizializzazione delle listview con le asyntask , in modo da evitare eventuali rallentamenti , lavorando quindi con thread separati  ;-) per il resto utilizzi già un buon adapter , sicuramente c'è codice in avanzo ma nulla di particolare ... poi vedo che implementi la classe ProvinceAdapter che adapter non è ma una semplice classe che fa chiamate verso il DB , lo trovo ridondante , alla fine hai già una classe DatabaseHelper che potrebbe contenere tutti i metodi e chiamate verso il DB , ma questo è solo un punto di vista , ognuno lo fa come più comodo , a me semplicemente non piace girare tra 100 finestre  :-P

Offline tonno16

  • Utente storico
  • *****
  • Post: 1169
  • Respect: +56
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:notifyDataSetChanged() Mi sta facendo impazzire.
« Risposta #9 il: 20 Aprile 2016, 22:56:57 CEST »
0
Io con un cursor avente 200 righe ho un caricamento istantaneo

Offline lcisetti

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Windows 7
Re:notifyDataSetChanged() Mi sta facendo impazzire.
« Risposta #10 il: 21 Aprile 2016, 18:56:55 CEST »
0
E come per magia l'istruzione "data.remove(position);" non funziona più con la ListView "piena"...

Oggi ho tuttavia reimplementato il tutto con un Cursor Adapter e mi sembra funzionare bene.

Non riesco a far più funzionare nel Cursor Adapter il click sull'iconcina "delete".

Funziona diversamente il click su un imageView presente nel layout di riga (row_item.xml) ?

Grazie.

Luca

Offline tonno16

  • Utente storico
  • *****
  • Post: 1169
  • Respect: +56
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:notifyDataSetChanged() Mi sta facendo impazzire.
« Risposta #11 il: 21 Aprile 2016, 20:56:00 CEST »
0
Puoi gestire il click nel adapter.