Unify the usage of cursors

Safer and less error-prone because:

* Always checks for null
* Checks for sizes
* Inits App/Apk lists at known capacity
* Properly closes all cursors

There are still one or two cursors that are not closed correctly and show
things like these:

W/CursorWrapperInner(19973): Cursor finalized without prior close()
This commit is contained in:
Daniel Martí 2014-03-22 00:11:56 +01:00
parent fc4a96acd8
commit 4f065492ef
5 changed files with 102 additions and 69 deletions

View File

@ -539,6 +539,7 @@ public class UpdateService extends IntentService implements ProgressListener {
int knownIdCount = cursor != null ? cursor.getCount() : 0; int knownIdCount = cursor != null ? cursor.getCount() : 0;
List<String> knownIds = new ArrayList<String>(knownIdCount); List<String> knownIds = new ArrayList<String>(knownIdCount);
if (cursor != null) {
if (knownIdCount > 0) { if (knownIdCount > 0) {
cursor.moveToFirst(); cursor.moveToFirst();
while (!cursor.isAfterLast()) { while (!cursor.isAfterLast()) {
@ -546,6 +547,8 @@ public class UpdateService extends IntentService implements ProgressListener {
cursor.moveToNext(); cursor.moveToNext();
} }
} }
cursor.close();
}
return knownIds; return knownIds;
} }

View File

@ -32,13 +32,16 @@ public class ApkProvider extends FDroidProvider {
} }
public static List<Apk> cursorToList(Cursor cursor) { public static List<Apk> cursorToList(Cursor cursor) {
List<Apk> apks = new ArrayList<Apk>(); int knownApkCount = cursor != null ? cursor.getCount() : 0;
List<Apk> apks = new ArrayList<Apk>(knownApkCount);
if (cursor != null) { if (cursor != null) {
if (knownApkCount > 0) {
cursor.moveToFirst(); cursor.moveToFirst();
while (!cursor.isAfterLast()) { while (!cursor.isAfterLast()) {
apks.add(new Apk(cursor)); apks.add(new Apk(cursor));
cursor.moveToNext(); cursor.moveToNext();
} }
}
cursor.close(); cursor.close();
} }
return apks; return apks;
@ -64,12 +67,15 @@ public class ApkProvider extends FDroidProvider {
ContentResolver resolver = context.getContentResolver(); ContentResolver resolver = context.getContentResolver();
Uri uri = getContentUri(id, versionCode); Uri uri = getContentUri(id, versionCode);
Cursor cursor = resolver.query(uri, projection, null, null, null); Cursor cursor = resolver.query(uri, projection, null, null, null);
if (cursor != null && cursor.getCount() > 0) { Apk apk = null;
if (cursor != null) {
if (cursor.getCount() > 0) {
cursor.moveToFirst(); cursor.moveToFirst();
return new Apk(cursor); apk = new Apk(cursor);
} else {
return null;
} }
cursor.close();
}
return apk;
} }
public static List<Apk> findByApp(Context context, String appId) { public static List<Apk> findByApp(Context context, String appId) {

View File

@ -40,13 +40,16 @@ public class AppProvider extends FDroidProvider {
} }
private static List<App> cursorToList(Cursor cursor) { private static List<App> cursorToList(Cursor cursor) {
List<App> apps = new ArrayList<App>(); int knownAppCount = cursor != null ? cursor.getCount() : 0;
List<App> apps = new ArrayList<App>(knownAppCount);
if (cursor != null) { if (cursor != null) {
if (knownAppCount > 0) {
cursor.moveToFirst(); cursor.moveToFirst();
while (!cursor.isAfterLast()) { while (!cursor.isAfterLast()) {
apps.add(new App(cursor)); apps.add(new App(cursor));
cursor.moveToNext(); cursor.moveToNext();
} }
}
cursor.close(); cursor.close();
} }
return apps; return apps;
@ -71,17 +74,20 @@ public class AppProvider extends FDroidProvider {
Cursor cursor = resolver.query(uri, projection, null, null, null ); Cursor cursor = resolver.query(uri, projection, null, null, null );
Set<String> categorySet = new HashSet<String>(); Set<String> categorySet = new HashSet<String>();
if (cursor != null) { if (cursor != null) {
if (cursor.getCount() > 0) {
cursor.moveToFirst(); cursor.moveToFirst();
while (!cursor.isAfterLast()) { while (!cursor.isAfterLast()) {
String categoriesString = cursor.getString(0); String categoriesString = cursor.getString(0);
if (categoriesString != null) { if (categoriesString != null) {
for( String s : Utils.CommaSeparatedList.make(categoriesString)) { for (String s : Utils.CommaSeparatedList.make(categoriesString)) {
categorySet.add(s); categorySet.add(s);
} }
} }
cursor.moveToNext(); cursor.moveToNext();
} }
} }
cursor.close();
}
List<String> categories = new ArrayList<String>(categorySet); List<String> categories = new ArrayList<String>(categorySet);
Collections.sort(categories); Collections.sort(categories);
@ -103,12 +109,15 @@ public class AppProvider extends FDroidProvider {
String[] projection) { String[] projection) {
Uri uri = getContentUri(appId); Uri uri = getContentUri(appId);
Cursor cursor = resolver.query(uri, projection, null, null, null); Cursor cursor = resolver.query(uri, projection, null, null, null);
if (cursor != null && cursor.getCount() > 0) { App app = null;
if (cursor != null) {
if (cursor.getCount() > 0) {
cursor.moveToFirst(); cursor.moveToFirst();
return new App(cursor); app = new App(cursor);
} else {
return null;
} }
cursor.close();
}
return app;
} }
public static void deleteAppsWithNoApks(ContentResolver resolver) { public static void deleteAppsWithNoApks(ContentResolver resolver) {

View File

@ -102,6 +102,7 @@ public class DBHelper extends SQLiteOpenHelper {
String[] columns = { "address", "_id" }; String[] columns = { "address", "_id" };
Cursor cursor = db.query(TABLE_REPO, columns, Cursor cursor = db.query(TABLE_REPO, columns,
"name IS NULL OR name = ''", null, null, null, null); "name IS NULL OR name = ''", null, null, null, null);
if (cursor != null) {
if (cursor.getCount() > 0) { if (cursor.getCount() > 0) {
cursor.moveToFirst(); cursor.moveToFirst();
while (!cursor.isAfterLast()) { while (!cursor.isAfterLast()) {
@ -116,6 +117,8 @@ public class DBHelper extends SQLiteOpenHelper {
cursor.moveToNext(); cursor.moveToNext();
} }
} }
cursor.close();
}
} }
} }
@ -254,19 +257,23 @@ public class DBHelper extends SQLiteOpenHelper {
private void migrateRepoTable(SQLiteDatabase db, int oldVersion) { private void migrateRepoTable(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 20) { if (oldVersion < 20) {
List<Repo> oldrepos = new ArrayList<Repo>(); List<Repo> oldrepos = new ArrayList<Repo>();
Cursor c = db.query(TABLE_REPO, Cursor cursor = db.query(TABLE_REPO,
new String[] { "address", "inuse", "pubkey" }, new String[] { "address", "inuse", "pubkey" },
null, null, null, null, null); null, null, null, null, null);
c.moveToFirst(); if (cursor != null) {
while (!c.isAfterLast()) { if (cursor.getCount() > 0) {
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Repo repo = new Repo(); Repo repo = new Repo();
repo.address = c.getString(0); repo.address = cursor.getString(0);
repo.inuse = (c.getInt(1) == 1); repo.inuse = (cursor.getInt(1) == 1);
repo.pubkey = c.getString(2); repo.pubkey = cursor.getString(2);
oldrepos.add(repo); oldrepos.add(repo);
c.moveToNext(); cursor.moveToNext();
}
}
cursor.close();
} }
c.close();
db.execSQL("drop table " + TABLE_REPO); db.execSQL("drop table " + TABLE_REPO);
db.execSQL(CREATE_TABLE_REPO); db.execSQL(CREATE_TABLE_REPO);
for (Repo repo : oldrepos) { for (Repo repo : oldrepos) {
@ -316,18 +323,22 @@ public class DBHelper extends SQLiteOpenHelper {
if (!columnExists(db, TABLE_REPO, "fingerprint")) if (!columnExists(db, TABLE_REPO, "fingerprint"))
db.execSQL("alter table " + TABLE_REPO + " add column fingerprint text"); db.execSQL("alter table " + TABLE_REPO + " add column fingerprint text");
List<Repo> oldrepos = new ArrayList<Repo>(); List<Repo> oldrepos = new ArrayList<Repo>();
Cursor c = db.query(TABLE_REPO, Cursor cursor = db.query(TABLE_REPO,
new String[] { "address", "pubkey" }, new String[] { "address", "pubkey" },
null, null, null, null, null); null, null, null, null, null);
c.moveToFirst(); if (cursor != null) {
while (!c.isAfterLast()) { if (cursor.getCount() > 0) {
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Repo repo = new Repo(); Repo repo = new Repo();
repo.address = c.getString(0); repo.address = cursor.getString(0);
repo.pubkey = c.getString(1); repo.pubkey = cursor.getString(1);
oldrepos.add(repo); oldrepos.add(repo);
c.moveToNext(); cursor.moveToNext();
}
}
cursor.close();
} }
c.close();
for (Repo repo : oldrepos) { for (Repo repo : oldrepos) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put("fingerprint", Utils.calcFingerprint(repo.pubkey)); values.put("fingerprint", Utils.calcFingerprint(repo.pubkey));

View File

@ -33,6 +33,7 @@ public class RepoProvider extends FDroidProvider {
if (cursor != null) { if (cursor != null) {
cursor.moveToFirst(); cursor.moveToFirst();
repo = new Repo(cursor); repo = new Repo(cursor);
cursor.close();
} }
return repo; return repo;
} }
@ -176,13 +177,16 @@ public class RepoProvider extends FDroidProvider {
ContentResolver resolver = context.getContentResolver(); ContentResolver resolver = context.getContentResolver();
String[] projection = { ApkProvider.DataColumns._COUNT_DISTINCT_ID }; String[] projection = { ApkProvider.DataColumns._COUNT_DISTINCT_ID };
Uri apkUri = ApkProvider.getRepoUri(repoId); Uri apkUri = ApkProvider.getRepoUri(repoId);
Cursor result = resolver.query(apkUri, projection, null, null, null); Cursor cursor = resolver.query(apkUri, projection, null, null, null);
if (result != null && result.getCount() > 0) { int count = 0;
result.moveToFirst(); if (cursor != null) {
return result.getInt(0); if (cursor.getCount() > 0) {
} else { cursor.moveToFirst();
return 0; count = cursor.getInt(0);
} }
cursor.close();
}
return count;
} }
} }