1

我製作了一個使用下載的SQLite數據庫的應用程序。要檢索其中的數據,我正在使用ContentProvider。當我需要讀取數據庫,我總是(我檢查了至少五次)使用這樣的代碼:已下載的SQLite數據庫和泄漏警告

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

回答

3

什麼會導致這些警示?

事實上,你不斷重新打開數據庫。打開數據庫一次,在onCreate(),不是每調用一次query()

雖然,誠實地說,如果你沒有實施完整的CRUD操作,我只是轉儲ContentProvider,因爲你一無所獲。它也可以讓你避免在循環中做一堆query()調用,並通過在SQLite查詢中使用IN運算符等來顯着提高性能。

+0

非常感謝您解決我的問題和智能建議,使我的應用程序更快!在4分鐘內,我會接受這個安撫者 – Vektor88 2014-10-18 11:53:34

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