Идиома, чтобы закрыть курсор

Какое из следующих двух я должен использовать, чтобы убедиться, что все курсоры закрыты?

    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:
Несколько вопросов:
1. Нужно ли нам называть курсор close() на курсоре с числом 0? 2. Поскольку в этом случае для первой идиомы, close() никогда не будет вызван. Он предполагает, что для курсора, не имеющего элементов, курсор никогда не будет открыт. Является ли это допустимым предположением?

Просьба сообщить.

Ответ 1

Ни один, а второй был ближе всего.

  • Вариант 1 неправильно закрывает Курсор, когда getCount() == 0
  • Вариант 2 оставляет блок finally, подверженным исключению нулевого указателя

Я бы использовал:

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

... или если вы ожидаете, что курсор будет нулевым, вы можете немного повернуть его на голову:

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

Ответ 2

Это еще лучше:

  • не использует c.getCount() - подсчет может потребовать дополнительной работы для базы данных и не нужен
  • инициализировать курсор перед блоком запроса, поэтому не удалось создать запрос

Код:

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

Обратите внимание, что c может быть пустым в случае ошибки или пустого курсора. См. fooobar.com/questions/127327/.... Тем не менее, я бы сообщил значение null возвращаемого значения в случае пустого курсора в качестве ошибки.

Ответ 3

Лучшая практика такова:

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.
}

Ответ 4

В зависимости от того, что вы ловите, но я бы сказал, второй, на всякий случай c.getCount() выдает исключение.

Кроме того, некоторые отступы не будут нарушаться:)

Ответ 5

Я бы сказал, первый, главным образом потому, что второй попытается вызвать c.close(), даже если c есть null. Кроме того, согласно документам getCount() не генерирует никаких исключений, поэтому нет необходимости включать его в блок try.

Ответ 6

Я думаю, что мой ответ самый лучший:

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

Ответ 7

Я думаю, что @skylarsutton - правильный ответ на этот вопрос. Тем не менее, я хочу оставить коды для вопроса (любые коды в ответах, кажется, имеют некоторые недостатки). Пожалуйста, используйте мой код.

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