2010-11-10 18 views
10

¿Cuál de los siguientes dos debería utilizar para asegurarme de que todos los cursores estén cerrados?Idioma para cerrar un cursor

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:
algunas preguntas:
1. ¿Necesitamos llamar a close() en un cursor que tiene el recuento de 0?
2. Porque en ese caso para la primera expresión idiomática, close() nunca se llamará. Se supone que para un cursor que no tenga elementos, el cursor nunca se abrirá. ¿Es esto una suposición válida?

Por favor, asesorar.

Respuesta

13

Ninguno, pero el segundo era el más cercano.

  • Opción 1 no se cierra correctamente cuando el cursor getCount() == 0
  • Opción 2 deja el bloque finally se expone a una excepción de puntero nulo

yo usaría:

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 si espera que el cursor sea nulo con frecuencia, puede darle un vuelco:

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

gracias por su respuesta! –

+0

no creo que use getCount es un buen método. si usas moveToFirst, puedes obtener un mejor rendimiento – wangzhengyi

+0

@wangzhengyi - Ese es un punto válido moveToFirst es más eficiente Y responde la pregunta de "¿hay algo en el conjunto de resultados? ... pero OP usó getCount() en su ejemplo, así que continuó aquí. –

0

Depende de lo que está atrapando, pero yo diría que el segundo, por si acaso c.getCount() hace una excepción.

Además, algunos sangría no estaría mal :)

0

yo diría que el primero de ellos, sobre todo porque el segundo tratará de llamar c.close() incluso si es cnull. Además, de acuerdo con los documentos, getCount() no arroja ninguna excepción, por lo que no es necesario incluirlo en el bloque try.

+0

¿Necesitamos llamar a close() en un cursor que tiene una cuenta de 0? Porque en ese caso para el primer idioma, close() nunca será llamado. Se supone que para un cursor que no tenga elementos, el cursor nunca se abrirá. ¿Es esto una suposición válida? –

+0

No. Un 'Cursor' debe cerrarse sin importar cuántos elementos tenga. – Felix

+0

Puede omitir la condición 'c.getCount()> 0'. De esta manera, el cursor siempre estará cerrado, y su bloque 'try' simplemente no hará nada. – Felix

1

La mejor práctica es la siguiente:

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

Me pregunto si en este caso es una mejor práctica poner el cursor en nulo, ya que es una variable local, el GC debería ser lo suficientemente inteligente como para manejarlo ¿no? – Shyri

3

Esto es incluso mejor:

  • no utiliza c.getCount() - recuento podría requerir un trabajo adicional para la base de datos y no es necesario
  • inicializa el cursor antes del bloque de consulta, por lo que al no crear la consulta no aparece el bloque finally

El código:

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

Tenga en cuenta que c podría ser nula en caso de error o un cursor vacío. Ver https://stackoverflow.com/a/16108435/952135. Sin embargo, me gustaría informar el valor de retorno nulo en caso de cursor vacío como un error.

+0

NPE es un problema, 'query' podría devolver' null'. – Pin

+0

Quería decir que no es necesaria ninguna verificación 'c! = Null' por fin. Si la consulta devuelve nulo, fallará con NPE, lo mismo que con el fragmento de Hemant. Y creo que el método 'query()' nunca devolverá nulo. Debería crear la consulta o lanzar una excepción, en cuyo caso no es necesario ejecutar el bloque finally. Este es un patrón de limpieza normal: crea recursos ... intenta ... trabaja ... finalmente ... limpia ... termina. Si la creación falla, se informa. Si el trabajo falla o tiene éxito, finalmente realiza la limpieza. Si comprende, elimine el voto negativo. Si no, por favor escribe. – Oliv

+1

Puede devolver nulo y está especificado en los documentos (ver ContentResolver.query). Además, verifique esto: http://stackoverflow.com/questions/13080540/what-causes-androids-contentresolver-query-to-return-null – Pin

-1

Creo que mi respuesta es la mejor:

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

si esta respuesta no es buena, por favor dime por qué piensas que este modelo es peor – wangzhengyi

-1

creo @ skylarsutton de una respuesta correcta a la pregunta.Sin embargo, quiero dejar códigos para la pregunta (cualquier código en las respuestas parece tener algunos defectos). Por favor considere usar mi código.

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(); 
    } 
}