可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Which of the following two should I be using to make sure that all the cursors are closed?
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:
A few questions:
1. Do we need to call close() on a cursor which has count of 0?
2. Because in that case for the first idiom, close() will never be called. It assumes that for a cursor having no elements, cursor will never be opened. Is this a valid assumption?
Please advise.
回答1:
Neither, but the second one was closest.
- Option 1 doesn't properly close the
Cursor when getCount() == 0
- Option 2 leaves the finally block exposed to a null pointer exception
I would use:
Cursor c = getCursor();
try {
if(c!=null && c.getCount()>0){
// do stuff with the cursor
}
}
catch(..) {
//Handle ex
}
finally {
if(c != null) {
c.close();
}
}
... or if you expect the cursor to be null frequently, you could turn it on its head a little bit:
Cursor c = getCursor();
if(c != null) {
try {
if(c.getCount()>0) {
// do stuff with the cursor
}
}
catch(..) {
//Handle ex
}
finally {
c.close();
}
}
回答2:
This is even better:
- does not use c.getCount() - counting might require extra work for the database and is not needed
- initialize the cursor before the query block, so failure to create the query is not followed by the finally block
The code:
Cursor c = query(....);
if (c != null) {
try {
while (c.moveToNext()) { // If empty or after last record it returns false.
// process row...
}
}
finally {
c.close();
}
}
Note that c
might be null in case of error or empty cursor. See https://stackoverflow.com/a/16108435/952135. I would report null return value in case of empty cursor as a bug, though.
回答3:
Best practice is the one below:
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:
Depends on what you're catching, but I'd say the second one, just in case c.getCount()
throws an exception.
Also, some indentation wouldn't go amiss :)
回答5:
I'd say the first one, mainly because the second one will try to call c.close()
even if c
is null
. Also, according to the docs, getCount()
doesn't throw any exceptions, so there's no need to include it in the try
block.
回答6:
I think my answer is the best one :
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:
I think @skylarsutton's is a right answer for the question. However, I want to leave codes for the question (any codes in answers seems to have some flaws). Please consider to use my code.
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();
}
}