#android #database #sqlite
#Android #База данных #sqlite
Вопрос:
у меня есть приложение, в котором постоянно генерируется это исключение…
04-25 18:47:38.024: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.035: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44dd1e68 on null that has not been deactivated or closed
04-25 18:47:38.035: INFO/dalvikvm(10290): at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.035: INFO/dalvikvm(10290): at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.044: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.064: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e4c048 on null that has not been deactivated or closed
04-25 18:47:38.064: INFO/dalvikvm(10290): at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.064: INFO/dalvikvm(10290): at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.074: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.094: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e35310 on null that has not been deactivated or closed
04-25 18:47:38.094: INFO/dalvikvm(10290): at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.094: INFO/dalvikvm(10290): at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.104: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.104: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e7f738 on null that has not been deactivated or closed
04-25 18:47:38.104: INFO/dalvikvm(10290): at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.104: INFO/dalvikvm(10290): at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.114: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.136: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e04a90 on null that has not been deactivated or closed
04-25 18:47:38.136: INFO/dalvikvm(10290): at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.136: INFO/dalvikvm(10290): at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.155: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.155: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e944f0 on null that has not been deactivated or closed
04-25 18:47:38.155: INFO/dalvikvm(10290): at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.155: INFO/dalvikvm(10290): at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.164: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.184: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e90548 on null that has not been deactivated or closed
04-25 18:47:38.184: INFO/dalvikvm(10290): at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.184: INFO/dalvikvm(10290): at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.194: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.194: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e6b0c8 on null that has not been deactivated or closed
04-25 18:47:38.194: INFO/dalvikvm(10290): at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.194: INFO/dalvikvm(10290): at dalvik.system.NativeStart.run(Native Method)
04-25 18:47:38.204: INFO/dalvikvm(10290): Uncaught exception thrown by finalizer (will be discarded):
04-25 18:47:38.225: INFO/dalvikvm(10290): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@44e4af40 on null that has not been deactivated or closed
04-25 18:47:38.237: INFO/dalvikvm(10290): at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
04-25 18:47:38.245: INFO/dalvikvm(10290): at dalvik.system.NativeStart.run(Native Method)
я не понимаю, почему это происходит. я закрыл все свои курсоры, а также я закрыл курсоры перед базами данных…
ie c.close()
предшествует db.close()
в чем может быть проблема?
заранее благодарю вас.
РЕДАКТИРОВАТЬ: я думаю, что этот класс вызывает исключение, потому что он единственный, кто имеет дело с базами данных
package com.helios.NauticDates;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
public class HandleDatabase {
public void executeSql(String query) {
SQLiteDatabase db = SQLiteDatabase.openDatabase(
"/data/data/com.helios.NauticDates/CalendarEvent.sqlitedb",
null, SQLiteDatabase.OPEN_READWRITE);
db.execSQL(query);
db.close();
}
public boolean checkCategory(String name) {
// TODO Auto-generated method stub
SQLiteDatabase db = SQLiteDatabase.openDatabase(
"/data/data/com.helios.NauticDates/CalendarEvent.sqlitedb",
null, SQLiteDatabase.OPEN_READWRITE);
String query = "select * from EventCategories where categoryname ='"
name "'";
Cursor c = db.rawQuery(query, null);
if (c.getCount() == 0) {
c.close();
db.close();
return true;
} else {
c.close();
db.close();
return false;
}
}
public String[][] getData(String[] columnnames, String tablename) {
SQLiteDatabase db = SQLiteDatabase.openDatabase(
"/data/data/com.helios.NauticDates/CalendarEvent.sqlitedb",
null, SQLiteDatabase.OPEN_READWRITE);
String query = "select ";
for (int i = 0; i < columnnames.length; i ) {
if (i == columnnames.length - 1)
query = columnnames[i] " ";
else
query = columnnames[i] ",";
}
query = "from " tablename " where eventid=128";
Cursor c = db.rawQuery(query, null);
String[][] result = new String[c.getColumnCount()][c.getCount()];
for (int i = 0; i < c.getColumnCount(); i ) {
c.moveToFirst();
for (int j = 0; j < c.getCount(); j ) {
result[i][j] = c.getString(c.getColumnIndex(columnnames[i]));
Log.i("getdata", result[i][j]);
c.moveToNext();
}
}
c.close();
db.close();
return result;
}
public boolean checkIfThereIsEvent(String cdate, Date currentdate) {
Date enddate = (Date) currentdate.clone();
enddate.setHours(0);
enddate.setMinutes(0);
enddate.setSeconds(0);
String edate = (String) android.text.format.DateFormat.format(
"yyyy-MM-dd", enddate);
Log.i("handledatabase", cdate "-" edate);
SQLiteDatabase db = SQLiteDatabase.openDatabase(
"/data/data/com.helios.NauticDates/CalendarEvent.sqlitedb",
null, SQLiteDatabase.OPEN_READWRITE);
String query = "SELECT datetime(startdat, 'unixepoch') AS std, datetime(enddat, 'unixepoch') AS end FROM EventDetails WHERE ((std <= '"
cdate
"' AND end >= '"
cdate
"' )||( date(enddat,'unixepoch') = '1970-01-01' AND date(startdat,'unixepoch') = '"
edate "')) LIMIT 1";
Log.i("thequery", query);
Cursor c = db.rawQuery(query, null);
if (c.getCount() > 0) {
c.close();
db.close();
return true;
}
{
c.close();
db.close();
return false;
}
}
public boolean checkEventInDatabase(String dateofchange, String eventid) {
SQLiteDatabase db = SQLiteDatabase.openDatabase(
"/data/data/com.helios.NauticDates/CalendarEvent.sqlitedb",
null, SQLiteDatabase.OPEN_READWRITE);
String query = "select * from EventDetails where eventid='" eventid "' limit 1";
Cursor c = db.rawQuery(query, null);
if(c.getCount()==0){
c.close();
db.close();
return false;
}
else{
query = "select * from EventDetails where eventid='" eventid "'and changed='" dateofchange "' limit 1";
c= db.rawQuery(query, null);
if(c.getCount()>0){
c.close();
db.close();
return true;
}
else{
c.close();
db.close();
return true;
}
}
}
public boolean checkIfEventChanged(String dateofchange, String eventid) {
SQLiteDatabase db = SQLiteDatabase.openDatabase(
"/data/data/com.helios.NauticDates/CalendarEvent.sqlitedb",
null, SQLiteDatabase.OPEN_READWRITE);
String query = "select * from EventDetails where eventid='" eventid "'and changed='" dateofchange "' limit 1";
Cursor c= db.rawQuery(query, null);
if(c.getCount()>0){
c.close();
db.close();
return false;
}
else{
c.close();
db.close();
return true;
}
}
}
Комментарии:
1. не могу сказать вам ничего больше, чем то, что говорится в сообщении об ошибке, не видя какого-либо кода.
2. обычно, когда выдается это исключение …?
3. пожалуйста, покажите нам полную ошибку, а не только первые 3 строки…
4. это полная ошибка, эта же ошибка повторяется снова и снова…
5. при каком условии вы получаете это выполнение…
Ответ №1:
Вы пропускаете else
ближе к концу checkIfThereIsEvent()
.
Если это не устраняет проблему, просто регистрируйте каждый, Cursor
который вы открываете самостоятельно с помощью вызова Log
, а затем сравните записи журнала, чтобы выяснить, какая Cursor
из них является утечкой.
Также:
- Никогда не проводите пути. Избавьтесь от
/data/data/com.helios.NauticDates
. Либо используйтеSQLiteOpenHelper
, либо используйтеgetDatabasePath()
. - Нет смысла постоянно открывать и закрывать вашу базу данных таким образом. Пожалуйста, рассмотрите возможность использования
SQLiteOpenHelper
, поместив эти методы в этот класс и сохранив своиSQLiteOpenHelper
дольше (например, время жизни вашей активности или службы или синглтон для всего вашего приложения)
Комментарии:
1. Else там не важно, потому что if содержит возврат, поэтому, когда оператор if имеет значение true, метод никогда не выполняет блок, который должен быть частью else
2. @WarrenFaith: Да, я вроде как предполагал, что все будет в порядке, но я хотел указать на это на всякий случай.
Ответ №2:
Дополнение к CommonsWare:
В вашем checkEventInDatabase()
вы переназначаете c
переменную, если c.getCount()
значение не равно 0, поэтому вы создаете курсор, который вы никогда не закрываете.
И пожалуйста: каждый раз, когда вы вызываете getCount()
или getColumnCount()
в цикле, бог убивает котенка! (см. getData()
)