Fetch images and media smarter; two indexes

This commit is contained in:
Martin Fietz 2015-11-25 15:46:55 +01:00
parent 732bda08a9
commit 5f845161be
2 changed files with 104 additions and 72 deletions

View File

@ -9,7 +9,9 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.Feed;
@ -189,53 +191,61 @@ public final class DBReader {
return result; return result;
} }
private static List<FeedItem> extractItemlistFromCursor( private static List<FeedItem> extractItemlistFromCursor(PodDBAdapter adapter,
PodDBAdapter adapter, Cursor itemlistCursor) { Cursor cursor) {
ArrayList<String> itemIds = new ArrayList<>(); List<FeedItem> result = new ArrayList<>(cursor.getCount());
List<FeedItem> items = new ArrayList<>(itemlistCursor.getCount());
if (itemlistCursor.moveToFirst()) { LongList imageIds = new LongList(cursor.getCount());
do { LongList itemIds = new LongList(cursor.getCount());
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<FeedItem> items, ArrayList<String> itemIds) {
List<FeedItem> itemsCopy = new ArrayList<>(items);
Cursor cursor = adapter.getFeedMediaCursorByItemID(itemIds
.toArray(new String[itemIds.size()]));
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
do { do {
int index = cursor.getColumnIndex(PodDBAdapter.KEY_FEEDITEM); int indexImage = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE);
long itemId = cursor.getLong(index); long imageId = cursor.getLong(indexImage);
// find matching feed item imageIds.add(imageId);
FeedItem item = getMatchingItemForMedia(itemId, itemsCopy);
if (item != null) { FeedItem item = FeedItem.fromCursor(cursor);
FeedMedia media = FeedMedia.fromCursor(cursor); result.add(item);
item.setMedia(media); itemIds.add(item.getId());
item.getMedia().setItem(item);
}
} while (cursor.moveToNext()); } while (cursor.moveToNext());
Map<Long,FeedImage> images = getFeedImages(adapter, imageIds.toArray());
Map<Long,FeedMedia> 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<Long,FeedMedia> getFeedMedia(PodDBAdapter adapter,
long... itemIds) {
ArrayList<String> ids = new ArrayList<>(itemIds.length);
for(long itemId : itemIds) {
ids.add(String.valueOf(itemId));
}
Map<Long,FeedMedia> 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, private static Feed extractFeedFromCursorRow(PodDBAdapter adapter,
@ -261,16 +271,6 @@ public final class DBReader {
return feed; return feed;
} }
private static FeedItem getMatchingItemForMedia(long itemId,
List<FeedItem> items) {
for (FeedItem item : items) {
if (item.getId() == itemId) {
return item;
}
}
return null;
}
static List<FeedItem> getQueue(PodDBAdapter adapter) { static List<FeedItem> getQueue(PodDBAdapter adapter) {
Log.d(TAG, "getQueue()"); Log.d(TAG, "getQueue()");
Cursor itemlistCursor = adapter.getQueueCursor(); Cursor itemlistCursor = adapter.getQueueCursor();
@ -844,21 +844,34 @@ public final class DBReader {
/** /**
* Searches the DB for a FeedImage of the given id. * 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 * @return The found object
*/ */
static FeedImage getFeedImage(PodDBAdapter adapter, final long id) { private static FeedImage getFeedImage(PodDBAdapter adapter, final long imageId) {
Cursor cursor = adapter.getImageCursor(id); 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<Long,FeedImage> getFeedImages(PodDBAdapter adapter, final long... ids) {
Cursor cursor = adapter.getImageCursor(ids);
Map<Long, FeedImage> result = new HashMap<>(cursor.getCount());
try { try {
if ((cursor.getCount() == 0) || !cursor.moveToFirst()) { if ((cursor.getCount() == 0) || !cursor.moveToFirst()) {
return null; return Collections.emptyMap();
} }
FeedImage image = FeedImage.fromCursor(cursor); do {
image.setId(id); FeedImage image = FeedImage.fromCursor(cursor);
return image; result.put(image.getId(), image);
} while(cursor.moveToNext());
} finally { } finally {
cursor.close(); cursor.close();
} }
return result;
} }
/** /**

View File

@ -13,6 +13,7 @@ import android.media.MediaMetadataRetriever;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import java.util.Arrays; import java.util.Arrays;
@ -188,6 +189,15 @@ public class PodDBAdapter {
+ TABLE_NAME_FEED_ITEMS + "_" + KEY_IMAGE + " ON " + TABLE_NAME_FEED_ITEMS + " (" + TABLE_NAME_FEED_ITEMS + "_" + KEY_IMAGE + " ON " + TABLE_NAME_FEED_ITEMS + " ("
+ KEY_IMAGE + ")"; + 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 " public static final String CREATE_INDEX_QUEUE_FEEDITEM = "CREATE INDEX "
+ TABLE_NAME_QUEUE + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_QUEUE + " (" + TABLE_NAME_QUEUE + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_QUEUE + " ("
+ KEY_FEEDITEM + ")"; + 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 * @return The cursor of the query
*/ */
public final Cursor getImageCursor(final long id) { public final Cursor getImageCursor(long... ids) {
Cursor c = db.query(TABLE_NAME_FEED_IMAGES, null, KEY_ID + "=?", String sql = "SELECT * FROM " + TABLE_NAME_FEED_IMAGES +
new String[]{String.valueOf(id)}, null, null, null); " WHERE " + KEY_ID + " IN (" + StringUtils.join(ids, ',') + ")";
Cursor c = db.rawQuery(sql, null);
return c; 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); return db.query(TABLE_NAME_FEED_MEDIA, null, KEY_ID + "=?", new String[]{String.valueOf(id)}, null, null, null);
} }
public final Cursor getFeedMediaCursorByItemID(String... mediaIds) { public final Cursor getFeedMediaCursor(String... itemIds) {
int length = mediaIds.length; int length = itemIds.length;
if (length > IN_OPERATOR_MAXIMUM) { if (length > IN_OPERATOR_MAXIMUM) {
Log.w(TAG, "Length of id array is larger than " Log.w(TAG, "Length of id array is larger than "
+ IN_OPERATOR_MAXIMUM + ". Creating multiple cursors"); + IN_OPERATOR_MAXIMUM + ". Creating multiple cursors");
int numCursors = (int) (((double) length) / (IN_OPERATOR_MAXIMUM)) + 1; int numCursors = (int) (((double) length) / (IN_OPERATOR_MAXIMUM)) + 1;
Cursor[] cursors = new Cursor[numCursors]; Cursor[] cursors = new Cursor[numCursors];
for (int i = 0; i < numCursors; i++) { for (int i = 0; i < numCursors; i++) {
int neededLength = 0; int neededLength;
String[] parts = null; String[] parts;
final int elementsLeft = length - i * IN_OPERATOR_MAXIMUM; final int elementsLeft = length - i * IN_OPERATOR_MAXIMUM;
if (elementsLeft >= IN_OPERATOR_MAXIMUM) { if (elementsLeft >= IN_OPERATOR_MAXIMUM) {
neededLength = 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, (i + 1)
* IN_OPERATOR_MAXIMUM); * IN_OPERATOR_MAXIMUM);
} else { } else {
neededLength = elementsLeft; neededLength = elementsLeft;
parts = Arrays.copyOfRange(mediaIds, i parts = Arrays.copyOfRange(itemIds, i
* IN_OPERATOR_MAXIMUM, (i * IN_OPERATOR_MAXIMUM) * IN_OPERATOR_MAXIMUM, (i * IN_OPERATOR_MAXIMUM)
+ neededLength); + neededLength);
} }
@ -1169,7 +1181,7 @@ public class PodDBAdapter {
return new MergeCursor(cursors); return new MergeCursor(cursors);
} else { } else {
return db.query(TABLE_NAME_FEED_MEDIA, null, KEY_FEEDITEM + " IN " 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 static class PodDBHelper extends SQLiteOpenHelper {
private final static int VERSION = 1040002; private final static int VERSION = 1040013;
private Context context; private Context context;
@ -1472,6 +1484,8 @@ public class PodDBAdapter {
db.execSQL(CREATE_INDEX_FEEDITEMS_FEED); db.execSQL(CREATE_INDEX_FEEDITEMS_FEED);
db.execSQL(CREATE_INDEX_FEEDITEMS_IMAGE); 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_FEEDMEDIA_FEEDITEM);
db.execSQL(CREATE_INDEX_QUEUE_FEEDITEM); db.execSQL(CREATE_INDEX_QUEUE_FEEDITEM);
db.execSQL(CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM); db.execSQL(CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM);
@ -1680,6 +1694,11 @@ public class PodDBAdapter {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " ADD COLUMN " + PodDBAdapter.KEY_LAST_PLAYED_TIME + " INTEGER DEFAULT 0"); + " 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()); EventBus.getDefault().post(ProgressEvent.end());
} }
} }