From 5f845161bedecc28c66c66041c2364d3f73632b8 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 25 Nov 2015 15:46:55 +0100 Subject: [PATCH] Fetch images and media smarter; two indexes --- .../antennapod/core/storage/DBReader.java | 131 ++++++++++-------- .../antennapod/core/storage/PodDBAdapter.java | 45 ++++-- 2 files changed, 104 insertions(+), 72 deletions(-) diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index a422a3b0c..42ca26079 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -9,7 +9,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; @@ -189,53 +191,61 @@ public final class DBReader { return result; } - private static List extractItemlistFromCursor( - PodDBAdapter adapter, Cursor itemlistCursor) { - ArrayList itemIds = new ArrayList<>(); - List items = new ArrayList<>(itemlistCursor.getCount()); + private static List extractItemlistFromCursor(PodDBAdapter adapter, + Cursor cursor) { + List result = new ArrayList<>(cursor.getCount()); - if (itemlistCursor.moveToFirst()) { - do { - int indexImage = itemlistCursor.getColumnIndex(PodDBAdapter.KEY_IMAGE); - long imageId = itemlistCursor.getLong(indexImage); - FeedImage image = null; - if (imageId != 0) { - image = getFeedImage(adapter, imageId); - } - - FeedItem item = FeedItem.fromCursor(itemlistCursor); - item.setImage(image); - - itemIds.add(String.valueOf(item.getId())); - - items.add(item); - } while (itemlistCursor.moveToNext()); - } - - extractMediafromItemlist(adapter, items, itemIds); - return items; - } - - private static void extractMediafromItemlist(PodDBAdapter adapter, - List items, ArrayList itemIds) { - - List itemsCopy = new ArrayList<>(items); - Cursor cursor = adapter.getFeedMediaCursorByItemID(itemIds - .toArray(new String[itemIds.size()])); + LongList imageIds = new LongList(cursor.getCount()); + LongList itemIds = new LongList(cursor.getCount()); if (cursor.moveToFirst()) { do { - int index = cursor.getColumnIndex(PodDBAdapter.KEY_FEEDITEM); - long itemId = cursor.getLong(index); - // find matching feed item - FeedItem item = getMatchingItemForMedia(itemId, itemsCopy); - if (item != null) { - FeedMedia media = FeedMedia.fromCursor(cursor); - item.setMedia(media); - item.getMedia().setItem(item); - } + int indexImage = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE); + long imageId = cursor.getLong(indexImage); + imageIds.add(imageId); + + FeedItem item = FeedItem.fromCursor(cursor); + result.add(item); + itemIds.add(item.getId()); } while (cursor.moveToNext()); + Map images = getFeedImages(adapter, imageIds.toArray()); + Map medias = getFeedMedia(adapter, itemIds.toArray()); + for(int i=0; i < result.size(); i++) { + FeedItem item = result.get(i); + long imageId = imageIds.get(i); + FeedImage image = images.get(imageId); + item.setImage(image); + FeedMedia media = medias.get(item.getId()); + item.setMedia(media); + if(media != null) { + media.setItem(item); + } + } } - cursor.close(); + return result; + } + + private static Map getFeedMedia(PodDBAdapter adapter, + long... itemIds) { + + ArrayList ids = new ArrayList<>(itemIds.length); + for(long itemId : itemIds) { + ids.add(String.valueOf(itemId)); + } + Map result = new HashMap<>(itemIds.length); + Cursor cursor = adapter.getFeedMediaCursor(ids.toArray(new String[0])); + try { + if (cursor.moveToFirst()) { + do { + int index = cursor.getColumnIndex(PodDBAdapter.KEY_FEEDITEM); + long itemId = cursor.getLong(index); + FeedMedia media = FeedMedia.fromCursor(cursor); + result.put(itemId, media); + } while (cursor.moveToNext()); + } + } finally { + cursor.close(); + } + return result; } private static Feed extractFeedFromCursorRow(PodDBAdapter adapter, @@ -261,16 +271,6 @@ public final class DBReader { return feed; } - private static FeedItem getMatchingItemForMedia(long itemId, - List items) { - for (FeedItem item : items) { - if (item.getId() == itemId) { - return item; - } - } - return null; - } - static List getQueue(PodDBAdapter adapter) { Log.d(TAG, "getQueue()"); Cursor itemlistCursor = adapter.getQueueCursor(); @@ -844,21 +844,34 @@ public final class DBReader { /** * Searches the DB for a FeedImage of the given id. * - * @param id The id of the object + * @param imageId The id of the object * @return The found object */ - static FeedImage getFeedImage(PodDBAdapter adapter, final long id) { - Cursor cursor = adapter.getImageCursor(id); + private static FeedImage getFeedImage(PodDBAdapter adapter, final long imageId) { + return getFeedImages(adapter, imageId).get(imageId); + } + + /** + * Searches the DB for a FeedImage of the given id. + * + * @param ids The id of the object + * @return The found object + */ + private static Map getFeedImages(PodDBAdapter adapter, final long... ids) { + Cursor cursor = adapter.getImageCursor(ids); + Map result = new HashMap<>(cursor.getCount()); try { if ((cursor.getCount() == 0) || !cursor.moveToFirst()) { - return null; + return Collections.emptyMap(); } - FeedImage image = FeedImage.fromCursor(cursor); - image.setId(id); - return image; + do { + FeedImage image = FeedImage.fromCursor(cursor); + result.put(image.getId(), image); + } while(cursor.moveToNext()); } finally { cursor.close(); } + return result; } /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 6ccb1d226..a601f4a03 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -13,6 +13,7 @@ import android.media.MediaMetadataRetriever; import android.text.TextUtils; import android.util.Log; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import java.util.Arrays; @@ -188,6 +189,15 @@ public class PodDBAdapter { + TABLE_NAME_FEED_ITEMS + "_" + KEY_IMAGE + " ON " + TABLE_NAME_FEED_ITEMS + " (" + KEY_IMAGE + ")"; + public static final String CREATE_INDEX_FEEDITEMS_PUBDATE = "CREATE INDEX IF NOT EXISTS " + + TABLE_NAME_FEED_ITEMS + "_" + KEY_PUBDATE + " ON " + TABLE_NAME_FEED_ITEMS + " (" + + KEY_PUBDATE + ")"; + + public static final String CREATE_INDEX_FEEDITEMS_READ = "CREATE INDEX IF NOT EXISTS " + + TABLE_NAME_FEED_ITEMS + "_" + KEY_READ + " ON " + TABLE_NAME_FEED_ITEMS + " (" + + KEY_READ + ")"; + + public static final String CREATE_INDEX_QUEUE_FEEDITEM = "CREATE INDEX " + TABLE_NAME_QUEUE + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_QUEUE + " (" + KEY_FEEDITEM + ")"; @@ -990,14 +1000,16 @@ public class PodDBAdapter { } /** - * Returns a cursor for a DB query in the FeedImages table for a given ID. + * Returns a cursor for a DB query in the FeedImages table for given IDs. * - * @param id ID of the FeedImage + * @param ids IDs of the FeedImages * @return The cursor of the query */ - public final Cursor getImageCursor(final long id) { - Cursor c = db.query(TABLE_NAME_FEED_IMAGES, null, KEY_ID + "=?", - new String[]{String.valueOf(id)}, null, null, null); + public final Cursor getImageCursor(long... ids) { + String sql = "SELECT * FROM " + TABLE_NAME_FEED_IMAGES + + " WHERE " + KEY_ID + " IN (" + StringUtils.join(ids, ',') + ")"; + Cursor c = db.rawQuery(sql, null); + return c; } @@ -1138,26 +1150,26 @@ public class PodDBAdapter { return db.query(TABLE_NAME_FEED_MEDIA, null, KEY_ID + "=?", new String[]{String.valueOf(id)}, null, null, null); } - public final Cursor getFeedMediaCursorByItemID(String... mediaIds) { - int length = mediaIds.length; + public final Cursor getFeedMediaCursor(String... itemIds) { + int length = itemIds.length; if (length > IN_OPERATOR_MAXIMUM) { Log.w(TAG, "Length of id array is larger than " + IN_OPERATOR_MAXIMUM + ". Creating multiple cursors"); int numCursors = (int) (((double) length) / (IN_OPERATOR_MAXIMUM)) + 1; Cursor[] cursors = new Cursor[numCursors]; for (int i = 0; i < numCursors; i++) { - int neededLength = 0; - String[] parts = null; + int neededLength; + String[] parts; final int elementsLeft = length - i * IN_OPERATOR_MAXIMUM; if (elementsLeft >= IN_OPERATOR_MAXIMUM) { neededLength = IN_OPERATOR_MAXIMUM; - parts = Arrays.copyOfRange(mediaIds, i + parts = Arrays.copyOfRange(itemIds, i * IN_OPERATOR_MAXIMUM, (i + 1) * IN_OPERATOR_MAXIMUM); } else { neededLength = elementsLeft; - parts = Arrays.copyOfRange(mediaIds, i + parts = Arrays.copyOfRange(itemIds, i * IN_OPERATOR_MAXIMUM, (i * IN_OPERATOR_MAXIMUM) + neededLength); } @@ -1169,7 +1181,7 @@ public class PodDBAdapter { return new MergeCursor(cursors); } else { return db.query(TABLE_NAME_FEED_MEDIA, null, KEY_FEEDITEM + " IN " - + buildInOperator(length), mediaIds, null, null, null); + + buildInOperator(length), itemIds, null, null, null); } } @@ -1442,7 +1454,7 @@ public class PodDBAdapter { */ private static class PodDBHelper extends SQLiteOpenHelper { - private final static int VERSION = 1040002; + private final static int VERSION = 1040013; private Context context; @@ -1472,6 +1484,8 @@ public class PodDBAdapter { db.execSQL(CREATE_INDEX_FEEDITEMS_FEED); db.execSQL(CREATE_INDEX_FEEDITEMS_IMAGE); + db.execSQL(CREATE_INDEX_FEEDITEMS_PUBDATE); + db.execSQL(CREATE_INDEX_FEEDITEMS_READ); db.execSQL(CREATE_INDEX_FEEDMEDIA_FEEDITEM); db.execSQL(CREATE_INDEX_QUEUE_FEEDITEM); db.execSQL(CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM); @@ -1680,6 +1694,11 @@ public class PodDBAdapter { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ADD COLUMN " + PodDBAdapter.KEY_LAST_PLAYED_TIME + " INTEGER DEFAULT 0"); } + if(oldVersion < 1040013) { + db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_PUBDATE); + db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_READ); + } + EventBus.getDefault().post(ProgressEvent.end()); } }