Idiom to close a cursor - android

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

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

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.

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

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 :)

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.

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

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

Related

Android Studio - How can I retrieve data from my database with a WHERE clause? [duplicate]

I am using custom adapter extending cursor adapter for displaying data in listview, to display particular phone number i have passed the id to a method in database class but it is showing
errorandroid.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
while placing debugger in the the method it is not going after the line
num = cursor.getString(cursor.getColumnIndex("ContactNumber"));
Can any one help me to solve it.
This is the code:
public String getNumberFromId(int id)
{
String num;
db= this.getReadableDatabase();
Cursor cursor = db.query(scheduletable, new String[] { "ContactNumber" },"_id="+id, null, null, null, null);
cursor.moveToFirst();
num = cursor.getString(cursor.getColumnIndex("ContactNumber"));
cursor.close();
db.close();
return num;
}
Whenever you are dealing with Cursors, ALWAYS check for null and check for moveToFirst() without fail.
if( cursor != null && cursor.moveToFirst() ){
num = cursor.getString(cursor.getColumnIndex("ContactNumber"));
cursor.close();
}
Place logs appropriately to see whether it is returning null or an empty cursor. According to that check your query.
Update Put both the checks in a single statement as mentioned by Jon in the comment below.
Update 2 Put the close() call within the valid cursor scope.
try this.. this will avoid an Exception being thrown when the cursor is empty..
if(cursor != null && cursor.moveToFirst()){
num = cursor.getString(cursor.getColumnIndex("ContactNumber"));
cursor.close();
}
First check this Condition before fetching data
if(cursor!=null && cursor.getCount()>0){
cursor.moveToFirst();
num = cursor.getString(cursor.getColumnIndex("ContactNumber"));
}
Check the return value from moveToFirst(), before you try to read anything from the cursor. It looks as if no results are being returned.
a save schema to query Cursors is
// just one
Cursor cursor = db.query(...);
if (cursor != null) {
if (cursor.moveToFirst()) {
value = cursor.getSomething();
}
cursor.close();
}
// multiple columns
Cursor cursor = db.query(...);
if (cursor != null) {
while (cursor.moveToNext()) {
values.add(cursor.getSomething());
}
cursor.close();
}
In case people are still looking:
Instead of searching for "ContactNumber" try searching for Phone.NUMBER. The tutorial has the code with more details: http://developer.android.com/training/basics/intents/result.html
try to uninstall the app and then again test it... actually the sqlite db is created only once when the app is first install... so if you think your logic is current then reinstalling the app will do the trick for you. !!!!

Using WHERE Clause SQLite database in Android?

This is my code:
public int getIdMotChuDe(String tenChuDe) {
int IDChuDe = 0;
try
{
Cursor c = null;
c = database.rawQuery(
"SELECT ChuDeID FROM DanhSachChuDe WHERE TenChuDe = ?"
, new String[] {tenChuDe});
c.moveToFirst();
IDChuDe = c.getInt(c.getColumnIndex("ChuDeID"));
c.close();
}
catch(Exception e)
{
e.printStackTrace();
}
return IDChuDe;
}
I'm trying to get ChuDeID from DanhSachChuDe table with condition in WHERE clause. But i don't know why this function always return 0.
Help me please. Thanks! Sorry because my english.
This could be because an Exception is being thrown. The code you are using is not correctly checking the state of your Cursor - it attempts to moveToFirst() before any checking too see if the object is not null.
Your code also assumes a result is always returned. This is bad practise, and should be avoided. A much safer and more common solution is the following:
if (cursor != null) {
// If the cursor has results, move the cursor to first row
if (cursor.moveToFirst()) {
do {
// YOUR METHODS HERE
// then move to next row
} while (cursor.moveToNext());
}
}

Cursor window could not be created from binder

1 Cursor cursor = contentResolver.query(MY_URI, new String[] { "first" }, null, null, null);
2 if (cursor != null) {
3 if (cursor.moveToFirst()) {
4 first = cursor.getString(cursor.getColumnIndex("first"));
5 cursor.close();
6 }
7 }
Then on line #3 (according to the logs), I every now and then I come across this exception (excerpt below):
android.database.CursorWindowAllocationException: Cursor window could not be created from binder.
at android.database.CursorWindow.<init>(CursorWindow.java:134)
at android.database.CursorWindow.<init>(CursorWindow.java:41)
at android.database.CursorWindow$1.createFromParcel(CursorWindow.java:709)
at android.database.CursorWindow$1.createFromParcel(CursorWindow.java:707)
at android.database.CursorWindow.newFromParcel(CursorWindow.java:718)
at android.database.BulkCursorProxy.getWindow(BulkCursorNative.java:196)
...
Any ideas why it is throwing this exception? Thanks!
I suspect the error may be related to you not closing your cursors properly all the time. Try:
Cursor cursor = contentResolver.query(MY_URI, new String[] { "first" }, null, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
first = cursor.getString(cursor.getColumnIndex("first"));
}
cursor.close(); ///// Changed here
}
The cursor should always be closed (regardless of whether or not its empty). Make sure the rest of your app is doing this as well.
Try another thread
new Thread(new Runnable(){ public void run(){
...here all code
}});
. But by Android SDK source codes look like 4.0.2_r1
130 private CursorWindow(Parcel source) {131 mStartPos = source.readInt();132 mWindowPtr = nativeCreateFromParcel(source);133 if (mWindowPtr == 0) {134 throw new CursorWindowAllocationException("Cursor window could not be "135 + "created from binder.");136 }137 mName = nativeGetName(mWindowPtr);138 mCloseGuard.open("close");139 }
where mWIndowPtr is Int
Try out this way:
if (cursor != null) {
cursor.moveToFirst();
do {
first = cursor.getString(cursor.getColumnIndex("first"));
}while(cursor.moveToNext());
}

android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0

I am using custom adapter extending cursor adapter for displaying data in listview, to display particular phone number i have passed the id to a method in database class but it is showing
errorandroid.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
while placing debugger in the the method it is not going after the line
num = cursor.getString(cursor.getColumnIndex("ContactNumber"));
Can any one help me to solve it.
This is the code:
public String getNumberFromId(int id)
{
String num;
db= this.getReadableDatabase();
Cursor cursor = db.query(scheduletable, new String[] { "ContactNumber" },"_id="+id, null, null, null, null);
cursor.moveToFirst();
num = cursor.getString(cursor.getColumnIndex("ContactNumber"));
cursor.close();
db.close();
return num;
}
Whenever you are dealing with Cursors, ALWAYS check for null and check for moveToFirst() without fail.
if( cursor != null && cursor.moveToFirst() ){
num = cursor.getString(cursor.getColumnIndex("ContactNumber"));
cursor.close();
}
Place logs appropriately to see whether it is returning null or an empty cursor. According to that check your query.
Update Put both the checks in a single statement as mentioned by Jon in the comment below.
Update 2 Put the close() call within the valid cursor scope.
try this.. this will avoid an Exception being thrown when the cursor is empty..
if(cursor != null && cursor.moveToFirst()){
num = cursor.getString(cursor.getColumnIndex("ContactNumber"));
cursor.close();
}
First check this Condition before fetching data
if(cursor!=null && cursor.getCount()>0){
cursor.moveToFirst();
num = cursor.getString(cursor.getColumnIndex("ContactNumber"));
}
Check the return value from moveToFirst(), before you try to read anything from the cursor. It looks as if no results are being returned.
a save schema to query Cursors is
// just one
Cursor cursor = db.query(...);
if (cursor != null) {
if (cursor.moveToFirst()) {
value = cursor.getSomething();
}
cursor.close();
}
// multiple columns
Cursor cursor = db.query(...);
if (cursor != null) {
while (cursor.moveToNext()) {
values.add(cursor.getSomething());
}
cursor.close();
}
In case people are still looking:
Instead of searching for "ContactNumber" try searching for Phone.NUMBER. The tutorial has the code with more details: http://developer.android.com/training/basics/intents/result.html
try to uninstall the app and then again test it... actually the sqlite db is created only once when the app is first install... so if you think your logic is current then reinstalling the app will do the trick for you. !!!!

Is there any library to track call time and sms time in android?

I want to a software to calculate call time and sms time usage in Android,
anyone has idea about any build-in library which handle such things ????
any way I can extract call logs in Android???
You could build the call usage data from the content provider CallLog.
The following code should work:
Cursor c = null;
try {
c = getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, null);
if (c != null && c.moveToFirst()) {
do {
int duration = c.getInt(c.getColumnIndex(CallLog.Calls.DURATION));
// do something with duration
} while (c.moveToNext());
}
} finally {
if (c != null) {
c.close();
}
}

Categories

Resources