2010-11-10 3 views
10

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

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

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

ответ

13

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

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

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

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

спасибо за ваш ответ! –

+0

Я не думаю, что использование getCount - хороший метод. если пользователь moveToFirst, вы можете получить более высокую производительность. – wangzhengyi

+0

@wangzhengyi - Это действительный пункт moveToFirst более результативен и отвечает на вопрос «есть ли что-либо в наборе результатов» ... но OP использовал getCount() в своем примере, чтобы я продолжил его здесь. –

0

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

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

0

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

+0

Нужно ли нам называть курсор close() на курсе, который имеет значение 0? Поскольку в этом случае для первой идиомы, close() никогда не будет вызван. Он предполагает, что для курсора, не имеющего элементов, курсор никогда не будет открыт. Действительно ли это предположение? –

+0

Нет. «Курсор» должен быть закрыт независимо от количества его элементов. – Felix

+0

Вы можете просто пропустить условие 'c.getCount()> 0'. Таким образом, ваш курсор всегда будет закрыт, и ваш блок 'try' просто ничего не сделает. – Felix

1

Лучшая практика является один ниже:

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

Интересно, если в этом случае лучше всего установить курсор в значение null, так как это локальная переменная, то GC должен быть достаточно умным, чтобы справиться с этим правильно? – Shyri

3

Это даже лучше:

  • не использует 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 может быть пустым в случае ошибки или пустой курсор. См. https://stackoverflow.com/a/16108435/952135. Тем не менее, я бы сообщал значение null возвращаемого значения в случае пустого курсора.

+0

NPE - проблема, 'query' может возвращать' null'. – Pin

+0

Я имел в виду, что в конце концов не требуется проверка 'c! = Null'. Если запрос возвращает значение null, он будет терпеть неудачу с NPE, так же, как и фрагмент Hemant. И я думаю, что метод 'query()' никогда не вернет null. Он должен создать запрос или выбросить исключение, и в этом случае вам не нужно запускать блок finally. Это нормальный шаблон очистки: создайте ресурс ... попробуйте ... сделайте работу ... наконец ... очистите ... конец. Если создание не удается, сообщается. Если работа завершается неудачно или завершается успешно, в конце происходит очистка. Если вы понимаете, пожалуйста, удалите отрицательный голос. Если нет, напишите. – Oliv

+1

Он может возвращать значение null и указан в документах (см. ContentResolver.query). Кроме того, проверьте это: http://stackoverflow.com/questions/13080540/what-causes-androids-contentresolver-query-to-return-null – Pin

-1

Я думаю, что мой ответ является правильным выбором:

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

Если этот ответ не подходит, скажите, пожалуйста, почему вы думаете, что эта модель хуже – wangzhengyi

-1

Я думаю, что @ 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(); 
    } 
} 
Смежные вопросы