2010-11-10 11 views
10

Którego z dwóch poniższych użyć, aby upewnić się, że wszystkie kursory są zamknięte?Idiom zamykający kursor

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:
kilka pytań: 1. Czy
musimy zadzwonić close() na kursor, który ma liczbę 0?
2. Ponieważ w przypadku pierwszego idiomu funkcja close() nigdy nie zostanie wywołana. Zakłada on, że dla kursora bez elementów kursor nigdy nie zostanie otwarty. Czy to jest prawidłowe założenie?

Prosimy o radę.

Odpowiedz

13

Nie, ale drugi był najbliżej.

  • Wariant 1 nie poprawnie zamknąć kursora podczas getCount() == 0
  • Opcja 2 pozostawia końcu bloku narażone na null pointer wyjątkiem

użyłbym:

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

... lub jeśli spodziewasz się, że kursor będzie często zerowany, możesz go nieco obrócić:

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

dzięki za odpowiedź! –

+0

Myślę, że nie używać getCount jest dobrą metodą. jeśli użytkownik moveToFirst, możesz uzyskać lepszą wydajność – wangzhengyi

+0

@wangzhengyi - To jest poprawny punkt moveToFirst jest bardziej wydajny i odpowiada na pytanie "czy jest coś w zestawie wyników" ... ale OP użył getCount() w ich przykładzie, więc kontynuował to tutaj. –

0

Zależy od tego, co łapiesz, ale powiedziałbym, że drugi, na wypadek gdyby c.getCount() rzucił wyjątek.

Ponadto, niektóre wgniecenia nie pójdzie źle :)

0

powiedziałbym pierwszy, głównie dlatego, że drugi będzie próbował zadzwonić c.close() nawet jeśli c jest null. Ponadto, zgodnie z dokumentami, getCount() nie generuje żadnych wyjątków, więc nie ma potrzeby włączania go do bloku try.

+0

Czy musimy wywołać metodę close() na kursorze, który ma wartość 0? Ponieważ w przypadku pierwszego idiomu funkcja close() nigdy nie zostanie wywołana. Zakłada on, że dla kursora bez elementów kursor nigdy nie zostanie otwarty. Czy to jest prawidłowe założenie? –

+0

Nr "Kursor" musi być zamknięty, niezależnie od tego, ile ma przedmiotów. – Felix

+0

Możesz po prostu pominąć warunek 'c.getCount()> 0'. W ten sposób kursor będzie zawsze zamknięty, a blok 'try' po prostu nie będzie działał. – Felix

1

Najlepsza praktyka jest jeden poniżej:

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

Zastanawiam się, czy w tym przypadku najlepiej jest ustawić kursor na wartość null, ponieważ jest to zmienna lokalna, GC powinien być wystarczająco inteligentny, aby poradzić sobie z tym poprawnie? – Shyri

3

To nawet lepiej:

  • nie używa c.getCount() - liczenie może wymagać dodatkowej pracy do bazy danych i nie jest potrzebne
  • zainicjować kursor przed blokiem zapytania, więc niepowodzenie w tworzeniu zapytania nie jest poprzedzane końcowym blokiem

Kod:

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

Zauważ, że c może być null w przypadku błędu lub pustym kursora. Zobacz https://stackoverflow.com/a/16108435/952135. Zanalizowałbym jednak wartość zwracaną null w przypadku pustego kursora jako błędu.

+0

NPE jest problemem, 'zapytanie' może zwrócić' null'. – Pin

+0

Miałem na myśli, że nie jest konieczne sprawdzenie 'c! = Null'. Jeśli zapytanie zwróci wartość NULL, nie powiedzie się z NPE, tak samo jak w przypadku fragmentu Hemant. I myślę, że metoda 'query()' nigdy nie zwróci wartości null. Powinien utworzyć zapytanie lub wyrzucić wyjątek, w którym to przypadku nie trzeba uruchamiać bloku finally. To jest normalny schemat czyszczenia: utwórz zasób ... spróbuj ... zrób to ... wreszcie ... posprzątaj ... koniec. Jeśli tworzenie nie powiedzie się, zostanie to zgłoszone. Jeśli praca się nie powiedzie lub się powiedzie, to w końcu robi porządek. Jeśli rozumiesz, usuń negatywny głos. Jeśli nie, napisz. – Oliv

+1

Może zwrócić wartość null i jest określona w dokumentach (zobacz ContentResolver.query). Sprawdź również: http://stackoverflow.com/questions/13080540/what-causes-androids-contentresolver-query-to-return-null – Pin

-1

myślę, że moja odpowiedź jest najlepszy:

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

jeśli ta odpowiedź nie jest dobra, proszę powiedz mi, dlaczego uważasz, że ten model jest gorszy – wangzhengyi

-1

myślę @ skylarsutton jest prawidłowa odpowiedź na pytanie.Jednak chcę zostawić kody na pytanie (wszelkie kody w odpowiedziach wydają się mieć pewne wady). Proszę rozważyć użycie mojego kodu.

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