Perché devo ottenere uno snapshot per posizionarmi su un record?
Perché devo posizionarmi su un record?
Perché devo agire su di essi uno per uno. Per dire "cancella un record" devo specificare il record stesso.
Proviamo a cancellare un solo record
reference= FirebaseDatabase.getInstance().getReference(); ... reference.child("-KUw45Hi6pkgGcRzwa7h").removeValue();e vediamo se funziona.
Certo che funziona! Ma il problema fondamentale è uno solo: io non conosco i nomi dei records, in quanto vengono assegnati dal sistema, e non posso conoscerli in anticipo (oltre al fatto che sono difficili da ricordare).
Dunque devo ricavarli.
Ammettiamo che io debba fare la stessa operazione senza conoscere il nome del record. Come faccio?
L'unica è ottenere uno snapshot del database stesso.
Ci provo, a ottenere un dataSnapshot. Ecco, così ottengo un dataSnapshot che figura fra i parametri.
Un dataSnapshot ha la proprietà getKey() che dovrebbe restituirmi il nome del nodo.
Ma se io faccio così su un dataSnapshot ottenuto dalla radice del database...
reference.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { System.out.println(dataSnapshot.getKey()); } @Override public void onCancelled(DatabaseError databaseError) { } });...ottengo null.
Però posso ottenere anche i dataSnapshot degli elementi "discendenti" della radice, ossia di ogni figlio di essa, vale a dire di ogni nodo, perché il dataSnapshot ha la proprietà getChildren(), che mi ottiene i dataSnapshot anche degli elementi figli.
reference.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { for(DataSnapshot child : dataSnapshot.getChildren()){ System.out.println(child.getKey()); } } @Override public void onCancelled(DatabaseError databaseError) { } });Con questa operazione ottengo i datasnapshot di tutti i figli.
Vediamo se mi dà i nomi "illeggibili".
10-25 16:42:43.585 7992-7992/? I/System.out: -KUwDcEfCy2-QPeLkNFS 10-25 16:42:43.585 7992-7992/? I/System.out: -KUwDcEnBfijEAoDzfkW 10-25 16:42:43.585 7992-7992/? I/System.out: -KUwDcEoAzah1_AhLlxCPerfetto!
Dunque per cancellare il primo record, facendo così, dobbiamo ottenere il nome del nodo in questo modo.
Però esso viene ottenuto insieme a tutti gli altri... Come fare per isolare quello che ci interessa?
Provo a fare così:
reference.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { List<String> lista=new ArrayList<String>(); for(DataSnapshot child : dataSnapshot.getChildren()){ System.out.println(child.getKey()); lista.add(child.getKey()); } reference.child(lista.get(0)).removeValue(); } @Override public void onCancelled(DatabaseError databaseError) { } });ossia metto i risultati in un'ArrayList e individuo il primo immesso come quello di indice zero.
Vediamo se funziona...
Sì! Funziona!
Ma posso anche usare direttamente il riferimento a un nodo figlio?
public void onDataChange(DataSnapshot dataSnapshot) { List<DatabaseReference> lista=new ArrayList<DatabaseReference>(); for(DataSnapshot child : dataSnapshot.getChildren()){ System.out.println(child.getKey()); lista.add(child.getRef()); } lista.get(0).removeValue(); }Sì, anche così funziona.
Ma posso usare anche un dataSnapshot di cui prendere il riferimento poi:
reference.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { List<DataSnapshot> lista=new ArrayList<DataSnapshot>(); for(DataSnapshot child : dataSnapshot.getChildren()){ System.out.println(child.getKey()); lista.add(child); } lista.get(0).getRef().removeValue(); }Quindi, alla fine il removeValue() si applica a un riferimento.
Questo riferimento si può ottenere ottenendo il DataSnapshot da cui ottenere il riferimento mediante getRef(), subito o successivamente, o ottenendo, sempre dal DataSnapshot il Value da cui poi ottenere il riferimento mediante il metodo .child() del riferimento della radice.
Ora, anziché andare per numero di ordine, volendo eliminare il primo (o anche il secondo eccetera) dei records, voglio eliminare solo quello che presenti determinate caratteristiche.
Devo costruirmi una query.
Provo...
Query query=reference.orderByChild("cognome").equalTo("Rossi");Sono un po' perplesso perché il child di reference è quello identificato dal nome irripetibile... ma forse il "child" di questo caso si riferisce anche ai "nipoti"...
Comunque questa perplessità servirà a farmi ricordare meglio la cosa.
Ora praticamente a una query io posso applicare un ValueEventListener?
Sembrerebbe di sì, e questo significa che ne posso ricavare un dataSnapshot e quindi un insieme di Children...
Vediamo:
bttRefreshFB.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { reference.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Query query=reference.orderByChild("cognome").equalTo("Rossi"); query.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { System.out.println(dataSnapshot.getChildrenCount()); } @Override public void onCancelled(DatabaseError databaseError) { } }); } @Override public void onCancelled(DatabaseError databaseError) { } }); } });Ecco: partendo dalla query ho ottenuto un dataSnapshot contenente tutti quei record che hanno un campo "cognome" uguale a "Rossi".
Ottengo, come mi aspettavo un numero di children pari a 1 in quanto solo un record è quello in cui "cognome" è uguale a "Rossi".
Bene, quindi dato che con la query posso selezionare, adesso voglio eliminare i records (ce n'è uno solo) in cui "cognome" equivale a "Minchia".
reference.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Query query=reference.orderByChild("cognome").equalTo("Minchia"); query.getRef().removeValue(); } @Override public void onCancelled(DatabaseError databaseError) { } });E invece così facendo ho eliminato tutti i records!
Perché?
Forse perché devo prima ottenere un dataSnapshot.
Ma è proprio indispensabile che ottenga la query nell'amito del metodo addListenerForSingleValueEvent?
No. Query agisce direttamente su reference, e mi seleziona i figli in relazione al criterio proposto.
Riscrivo:
bttRefreshFB.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { Query query=reference.orderByChild("cognome").equalTo("Minchia"); query.getRef().removeValue(); } });Provo...
E ottengo lo stesso risultato.
Query è una selezione di un riferimento, quindi va soggetta agli stessi criteri di un riferimento.
bttRefreshFB.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { Query query=reference.orderByChild("cognome").equalTo("Minchia"); query.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { for(DataSnapshot child : dataSnapshot.getChildren()){ child.getRef().removeValue(); } } @Override public void onCancelled(DatabaseError databaseError) { } }); } });
Perfetto!!! Adesso funziona!
Nessun commento:
Posta un commento