2010-11-10 2 views
10

Quale dei seguenti due dovrei utilizzare per accertarmi che tutti i cursori siano chiusi?Idioma per chiudere un cursore

Cursor c = getCursor(); 

    if(c!=null && c.getCount()>0){ 
     try{ 
      // read values from cursor 
     }catch(..){} 
     finally{ 
      c.close(); 
     } 
    }//end if 

    OR 

    Cursor c = getCursor(); 
    try{ 
     if(c!=null && c.getCount()>0){ 
      // read values from cursor 
     }//end if 
    }catch(..){ 

    }finally{ 
     c.close(); 
    } 

EDIT:
alcune domande:
1. Abbiamo bisogno di chiamare close() su un cursore che ha conteggio di 0?
2. Perché in questo caso per il primo idioma, close() non verrà mai chiamato. Presume che per un cursore che non ha elementi, il cursore non verrà mai aperto. È un presupposto valido?

Si prega di avvisare.

risposta

13

Né, ma il secondo era il più vicino.

  • Opzione 1 non correttamente chiude il cursore quando getCount() == 0
  • Opzione 2 lascia il blocco finally esposto ad un'eccezione di puntatore nullo

userei:

Cursor c = getCursor(); 
try { 
    if(c!=null && c.getCount()>0){ 
     // do stuff with the cursor 
    } 
} 
catch(..) { 
    //Handle ex 
} 
finally { 
    if(c != null) { 
     c.close(); 
    } 
} 

... o se si prevede che il cursore sia frequentemente nullo, è possibile ruotarlo un po 'sulla sua testa:

Cursor c = getCursor(); 
if(c != null) { 
    try { 
     if(c.getCount()>0) { 
      // do stuff with the cursor 
     } 
    } 
    catch(..) { 
     //Handle ex 
    } 
    finally { 
     c.close(); 
    } 
} 
+0

grazie per la tua risposta! –

+0

Non penso che usare getCount sia un buon metodo. se si usa moveToFirst, è possibile ottenere prestazioni migliori – wangzhengyi

+0

@wangzhengyi - Quella è una mossa punto validaToFirst è più performante E risponde alla domanda "c'è qualcosa nel set di risultati" ... ma l'OP ha usato getCount() nel loro esempio così io ha continuato qui. –

0

Dipende da ciò che stai catturando, ma direi il secondo, nel caso in cui c.getCount() genera un'eccezione.

Inoltre, alcuni rientro non guasterebbe :)

0

direi che la prima, soprattutto perché il secondo proverà a chiamare c.close() anche se c è null. Inoltre, secondo i documenti, getCount() non genera eccezioni, quindi non è necessario includerlo nel blocco try.

+0

Dobbiamo chiamare close() su un cursore che ha il conteggio di 0? Perché in quel caso per il primo idioma, close() non verrà mai chiamato. Presume che per un cursore che non ha elementi, il cursore non verrà mai aperto. È un presupposto valido? –

+0

No. Un 'Cursore' deve essere chiuso indipendentemente dal numero di elementi. – Felix

+0

Puoi semplicemente saltare la condizione 'c.getCount()> 0'. In questo modo, il tuo cursore sarà sempre chiuso e il tuo blocco 'try' semplicemente non farà nulla. – Felix

1

migliore pratica è quella qui sotto:

Cursor c = null;  
try {   
    c = query(....);  
    while (c.moveToNext()) { // If empty or next to last record it returns false.  
     // do stuff..  
    } 
} finally { 
    if (c != null && !c.isClosed()) { // If cursor is empty even though should close it.  
    c.close(); 
    c = null; // high chances of quick memory release. 
} 
+0

Mi chiedo se in questo caso sia davvero consigliabile impostare il cursore su null, poiché è una variabile locale, il GC dovrebbe essere abbastanza intelligente per gestirlo correttamente? – Shyri

3

Questo è ancora meglio:

  • non usa c.getCount() - Il conteggio potrebbe richiedere lavoro supplementare per il database e non è necessario
  • inizializzare il cursore prima del blocco di query, quindi l'errore di creazione della query non è seguito dal blocco finally

Il codice:

Cursor c = query(....); 
if (c != null) { 
    try {   
     while (c.moveToNext()) { // If empty or after last record it returns false.  
      // process row... 
     } 
    } 
    finally { 
     c.close(); 
    } 
} 

noti che c potrebbe essere nullo in caso di errore o cursore vuoto. Vedi https://stackoverflow.com/a/16108435/952135. Tuttavia, segnalerei il valore di ritorno nullo in caso di cursore vuoto come un bug.

+0

NPE è un problema, 'query' potrebbe restituire' null'. – Pin

+0

Intendo dire che non è necessario il controllo 'c! = Null' in fine. Se la query restituisce null, fallirà con NPE, come nel caso dello snippet di Hemant. E penso che il metodo 'query()' non restituirà mai nulla. Dovrebbe creare la query o generare un'eccezione, nel qual caso non è necessario eseguire il blocco finally. Questo è normale schema di pulizia: creare risorse ... provare ... lavorare ... finalmente ... ripulire ... fine. Se la creazione fallisce, viene segnalata. Se il lavoro fallisce o ha esito positivo, finalmente effettua la pulizia. Se hai capito, rimuovi il voto negativo. In caso contrario, si prega di scrivere. – Oliv

+1

Può restituire null ed è specificato nei documenti (vedere ContentResolver.query). Inoltre, verifica questo: http://stackoverflow.com/questions/13080540/what-causes-androids-contentresolver-query-to-return-null – Pin

-1

penso che la mia risposta è la migliore:

Cursor cursor = null; 

    try { 
     cursor = rsd.rawQuery(querySql, null); 
     if (cursor.moveToFirst()) { 
      do { 
       // select your need data from database 
      } while (cursor.moveToNext()); 
     } 
    } finally { 
     if (cursor != null && !cursor.isClosed()) { 
      cursor.close(); 
      cursor = null; 
     } 
    } 
+0

se questa risposta non è buona, per favore dimmi perché pensi che questo modello sia peggio – wangzhengyi

-1

Penso @ skylarsutton di una risposta giusta per la domanda.Tuttavia, voglio lasciare i codici per la domanda (qualsiasi codice in risposta sembra avere alcuni difetti). Per favore considera di usare il mio codice.

Cursor c = query(....); 
if (c != null) { 
    try {   
     //You have to use moveToFirst(). There is no quarantee that a cursor is located at the beginning. 
     for(c.moveToFirst();!c.isAfterLast();c.moveToNext()) { 
      // process row... 
     } 
    } 
    finally { 
     c.close(); 
    } 
}