2010-11-10 55 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(); 
    } 

编辑:
几个问题:
1.我们需要调用close()在具有0计数的光标?
2.因为在这种情况下,第一个习惯用法,close()永远不会被调用。它假定对于没有元素的游标,游标永远不会被打开。这是一个有效的假设吗?

请指教。

回答

13

也没有,但第二个是最接近的。

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

感谢您的回答! – 2010-11-11 17:19:31

+0

我不认为使用getCount是一个好方法。如果你用户moveToFirst,你可以得到更好的性能 – wangzhengyi 2014-09-13 02:03:04

+0

@wangzhengyi - 这是一个有效的点moveToFirst更高性能,并回答“结果集中是否有任何东西”的问题......但OP在他们的例子中使用了getCount(),所以我继续在这里。 – 2014-09-14 22:57:55

0

取决于你在抓什么,但我会说第二个,以防万一c.getCount()引发异常。

此外,一些缩进不会不妥去:)

0

我想说的第一个,主要是因为第二个会尝试调用c.close()即使cnull。此外,根据文档,getCount()不会抛出任何异常,因此无需将其包含在try块中。

+0

我们是否需要在计数为0的游标上调用close()?因为在那种情况下,第一个习惯用法,close()永远不会被调用。它假定对于没有元素的游标,游标永远不会被打开。这是一个有效的假设吗? – 2010-11-10 12:56:17

+0

不需要。无论有多少物品,“光标”都需要关闭。 – Felix 2010-11-10 14:41:28

+0

您可以跳过'c.getCount()> 0'条件。这样,你的光标总是会关闭的,你的'try'块将不会做任何事情。 – Felix 2010-11-10 14:44:19

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

我想知道在这种情况下是否最好的做法是将游标设置为空,因为它是一个局部变量,GC应该足够聪明来处理它了吗? – Shyri 2017-01-19 14:31:40

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。尽管如此,我将在空游标作为错误的情况下报告空返回值。

+0

NPE是个问题,'query'可能返回'null'。 – Pin 2014-02-11 15:35:40

+0

我的意思是最后不需要'c!= null'检查。如果查询返回null,则NPE将失败,与Hemant的代码片段相同。我认为'query()'方法永远不会返回null。它应该创建查询或抛出异常,在这种情况下,您不需要运行finally块。这是正常的清理模式:创建资源...尝试...做功...最后...清理...结束。如果创建失败,则会报告。如果工作失败或成功,最后进行清理。如果您了解,请删除否定的投票。如果没有,请写。 – Oliv 2014-02-17 09:12:20

+1

它可以返回null,并在文档中指定它(请参阅ContentResolver.query)。此外,请检查此:http://stackoverflow.com/questions/13080540/what-c​​auses-androids-contentresolver-query-to-return-null – Pin 2014-02-18 10:13:39

-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 2014-09-15 06:29:14

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