我创建了一个使用下载的SQLite数据库的应用程序。要检索其中的数据,我使用ContentProvider
。当我需要阅读数据库时,我总是(我已经检查了至少五次)使用这样的代码:
Cursor c = getContext().getContentResolver().query(MyContentProvider.ITEMSURI,
projection,where,null,null);
if(c.moveToFirst()){
while(!c.isAfterLast()){
itemsList.add(cursorToItem(c));
c.moveToNext();
}
}
if(c!=null) c.close();
但是我不断收到很多这样的错误(我在for循环中创建了一系列查询):
10-18 13:16:01.709: W/SQLiteConnectionPool(27704): A SQLiteConnection object
for database '/storage/emulated/0/MyAPP/mydb.sqlite' was leaked!
Please fix your application to end transactions in progress properly and to
close the database when it is no longer needed.
什么可能导致所有这些警告?游标始终关闭,在ContentProvider
中不需要关闭数据库。
代码:
这是管理数据库的类:
public class OpenMyDBHelper{
private static final String DB_NAME = "mydb.sqlite";
private static final File DB_PATH = new File(
MyAppFolderManager.getInternalMemoryFolder(), DB_NAME);
private SQLiteDatabase db;
public SQLiteDatabase open() {
db = SQLiteDatabase.openDatabase(DB_PATH.getAbsolutePath(), null,
SQLiteDatabase.OPEN_READONLY);
return db;
}
public void close() {
db.close();
}
}
这是我的ContentProvider
子类:
public class MyContentProvider extends ContentProvider {
private OpenMyDBHelper db;
//static paths/Uri definitions....
private final static int ITEMS = 1;
private static final UriMatcher sURIMatcher = new UriMatcher(
UriMatcher.NO_MATCH);
static {
sURIMatcher.addURI(AUTHORITY, ITEMS_PATH, ITEMS);
}
@Override
public boolean onCreate() {
db = new OpenMyDBHelper();
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Cursor cursor = null;
SQLiteDatabase database = db.open();
int uriType = sURIMatcher.match(uri);
switch (uriType) {
case ITEMS:
cursor = database.query(Constants.TABLE_ITEMS,
projection, selection, selectionArgs, null,null,
null);
cursor.setNotificationUri(getContext().getContentResolver(), ITEMSURI);
break;
default:
throw new IllegalArgumentException("Unknown URI (" + uri + ")");
}
return cursor;
}
@Override
public String getType(Uri uri) {
return null;
}
//It's just a read-only db, I don't need the CUD operations...
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
return 0;
}
}
答案 0 :(得分:3)
什么可能导致所有这些警告?
您不断重新打开数据库。在onCreate()
中打开数据库一次,而不是每次query()
来电。
尽管如此,如果你没有实现完整的CRUD操作,我只是转储ContentProvider
,因为你没有获得任何东西。它还可以让您避免在循环中执行大量query()
调用,并通过在SQLite查询中使用IN
运算符来显着提高性能。
答案 1 :(得分:1)
如果必须多次使用getReadableDatabase:
您可以使用this.close从泄漏中关闭数据库。 示例:
public String getAdditionalInfo(final int id) {
yourDB = this.getReadableDatabase();
Cursor cursor = yourDB.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
return cursor.getString(0);
}
cursor.close();
this.close();// You add this line
return "";
}