Android SQLLiteOpenHelper n’aide pas vraiment
Arg! Je viens de découvrir avec horreur que <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html">SQLLiteOpenHelper</a>
n’était pas thread-safe.
Plus précisément, lorsque l’on fait un <a href="http://developer.android.com/reference/android/content/ContentProvider.html">ContentProvider</a>
, on a envie d’écrire quelque chose comme:
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();
final String groupBy = null;
final String having = null;
switch (sUriMatcher.match(uri)) {
case URI\_MATCH\_1:
return db.query(TABLE1, projection,
selection, selectionArgs, groupBy, having, sortOrder);
default:
throw new IllegalArgumentException(« Unknown URI » + uri);
}
}
}
Hé bien, cela peut lever une exception
10-11 21:17:24.624: E/AndroidRuntime(29832): Caused by: java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
En fait, la base qu’on manipule est fermée d’office lorsque
- un autre thread appelle
getWritableDatabase()
. - un autre thread appelle
close()
sur une autre instance de database, obtenue par un autreSQLLiteOpenHelper
Conclusion:
- Réutiliser le même
SQLLiteOpenHelper
- N’utiliser que
getWritableDatabase()
Plus de détails dans un article en anglais Database pitfalls.