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.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<FeedItem> extractItemlistFromCursor(
PodDBAdapter adapter, Cursor itemlistCursor) {
ArrayList<String> itemIds = new ArrayList<>();
List<FeedItem> items = new ArrayList<>(itemlistCursor.getCount());
private static List<FeedItem> extractItemlistFromCursor(PodDBAdapter adapter,
Cursor cursor) {
List<FeedItem> 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<FeedItem> items, ArrayList<String> itemIds) {
List<FeedItem> 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<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,
@ -261,16 +271,6 @@ public final class DBReader {
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) {
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<Long,FeedImage> getFeedImages(PodDBAdapter adapter, final long... ids) {
Cursor cursor = adapter.getImageCursor(ids);
Map<Long, FeedImage> 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;
}
/**

View File

@ -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());
}
}