下载了SQLite数据库和泄漏警告

时间:2014-10-18 11:43:02

标签: android sqlite android-contentprovider android-contentresolver

我创建了一个使用下载的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;
    }
}

2 个答案:

答案 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 "";
    }