Base cache key on info type instead of item type
It didn't really made sense to consider two cache keys as equal based on the type of items contained within that list.
This commit is contained in:
parent
1d8850d1b2
commit
04bdc1cc0b
3 changed files with 68 additions and 40 deletions
|
@ -72,7 +72,6 @@ import org.schabi.newpipe.error.ErrorUtil;
|
||||||
import org.schabi.newpipe.error.ReCaptchaActivity;
|
import org.schabi.newpipe.error.ReCaptchaActivity;
|
||||||
import org.schabi.newpipe.error.UserAction;
|
import org.schabi.newpipe.error.UserAction;
|
||||||
import org.schabi.newpipe.extractor.Image;
|
import org.schabi.newpipe.extractor.Image;
|
||||||
import org.schabi.newpipe.extractor.InfoItem;
|
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
|
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException;
|
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException;
|
||||||
|
@ -107,16 +106,17 @@ import org.schabi.newpipe.player.ui.VideoPlayerUi;
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
import org.schabi.newpipe.util.DeviceUtils;
|
import org.schabi.newpipe.util.DeviceUtils;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
|
import org.schabi.newpipe.util.InfoCache;
|
||||||
import org.schabi.newpipe.util.ListHelper;
|
import org.schabi.newpipe.util.ListHelper;
|
||||||
import org.schabi.newpipe.util.Localization;
|
import org.schabi.newpipe.util.Localization;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
import org.schabi.newpipe.util.PermissionHelper;
|
import org.schabi.newpipe.util.PermissionHelper;
|
||||||
import org.schabi.newpipe.util.image.PicassoHelper;
|
import org.schabi.newpipe.util.PlayButtonHelper;
|
||||||
import org.schabi.newpipe.util.StreamTypeUtil;
|
import org.schabi.newpipe.util.StreamTypeUtil;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
import org.schabi.newpipe.util.external_communication.KoreUtils;
|
import org.schabi.newpipe.util.external_communication.KoreUtils;
|
||||||
import org.schabi.newpipe.util.external_communication.ShareUtils;
|
import org.schabi.newpipe.util.external_communication.ShareUtils;
|
||||||
import org.schabi.newpipe.util.PlayButtonHelper;
|
import org.schabi.newpipe.util.image.PicassoHelper;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -1445,7 +1445,7 @@ public final class VideoDetailFragment
|
||||||
super.showLoading();
|
super.showLoading();
|
||||||
|
|
||||||
//if data is already cached, transition from VISIBLE -> INVISIBLE -> VISIBLE is not required
|
//if data is already cached, transition from VISIBLE -> INVISIBLE -> VISIBLE is not required
|
||||||
if (!ExtractorHelper.isCached(serviceId, url, InfoItem.InfoType.STREAM)) {
|
if (!ExtractorHelper.isCached(serviceId, url, InfoCache.Type.STREAM)) {
|
||||||
binding.detailContentRootHiding.setVisibility(View.INVISIBLE);
|
binding.detailContentRootHiding.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.text.HtmlCompat;
|
import androidx.core.text.HtmlCompat;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
@ -113,14 +114,14 @@ public final class ExtractorHelper {
|
||||||
public static Single<StreamInfo> getStreamInfo(final int serviceId, final String url,
|
public static Single<StreamInfo> getStreamInfo(final int serviceId, final String url,
|
||||||
final boolean forceLoad) {
|
final boolean forceLoad) {
|
||||||
checkServiceId(serviceId);
|
checkServiceId(serviceId);
|
||||||
return checkCache(forceLoad, serviceId, url, InfoItem.InfoType.STREAM,
|
return checkCache(forceLoad, serviceId, url, InfoCache.Type.STREAM,
|
||||||
Single.fromCallable(() -> StreamInfo.getInfo(NewPipe.getService(serviceId), url)));
|
Single.fromCallable(() -> StreamInfo.getInfo(NewPipe.getService(serviceId), url)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Single<ChannelInfo> getChannelInfo(final int serviceId, final String url,
|
public static Single<ChannelInfo> getChannelInfo(final int serviceId, final String url,
|
||||||
final boolean forceLoad) {
|
final boolean forceLoad) {
|
||||||
checkServiceId(serviceId);
|
checkServiceId(serviceId);
|
||||||
return checkCache(forceLoad, serviceId, url, InfoItem.InfoType.CHANNEL,
|
return checkCache(forceLoad, serviceId, url, InfoCache.Type.CHANNEL,
|
||||||
Single.fromCallable(() ->
|
Single.fromCallable(() ->
|
||||||
ChannelInfo.getInfo(NewPipe.getService(serviceId), url)));
|
ChannelInfo.getInfo(NewPipe.getService(serviceId), url)));
|
||||||
}
|
}
|
||||||
|
@ -130,7 +131,7 @@ public final class ExtractorHelper {
|
||||||
final boolean forceLoad) {
|
final boolean forceLoad) {
|
||||||
checkServiceId(serviceId);
|
checkServiceId(serviceId);
|
||||||
return checkCache(forceLoad, serviceId,
|
return checkCache(forceLoad, serviceId,
|
||||||
listLinkHandler.getUrl(), InfoItem.InfoType.CHANNEL,
|
listLinkHandler.getUrl(), InfoCache.Type.CHANNEL_TAB,
|
||||||
Single.fromCallable(() ->
|
Single.fromCallable(() ->
|
||||||
ChannelTabInfo.getInfo(NewPipe.getService(serviceId), listLinkHandler)));
|
ChannelTabInfo.getInfo(NewPipe.getService(serviceId), listLinkHandler)));
|
||||||
}
|
}
|
||||||
|
@ -145,10 +146,11 @@ public final class ExtractorHelper {
|
||||||
listLinkHandler, nextPage));
|
listLinkHandler, nextPage));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Single<CommentsInfo> getCommentsInfo(final int serviceId, final String url,
|
public static Single<CommentsInfo> getCommentsInfo(final int serviceId,
|
||||||
|
final String url,
|
||||||
final boolean forceLoad) {
|
final boolean forceLoad) {
|
||||||
checkServiceId(serviceId);
|
checkServiceId(serviceId);
|
||||||
return checkCache(forceLoad, serviceId, url, InfoItem.InfoType.COMMENT,
|
return checkCache(forceLoad, serviceId, url, InfoCache.Type.COMMENTS,
|
||||||
Single.fromCallable(() ->
|
Single.fromCallable(() ->
|
||||||
CommentsInfo.getInfo(NewPipe.getService(serviceId), url)));
|
CommentsInfo.getInfo(NewPipe.getService(serviceId), url)));
|
||||||
}
|
}
|
||||||
|
@ -175,7 +177,7 @@ public final class ExtractorHelper {
|
||||||
final String url,
|
final String url,
|
||||||
final boolean forceLoad) {
|
final boolean forceLoad) {
|
||||||
checkServiceId(serviceId);
|
checkServiceId(serviceId);
|
||||||
return checkCache(forceLoad, serviceId, url, InfoItem.InfoType.PLAYLIST,
|
return checkCache(forceLoad, serviceId, url, InfoCache.Type.PLAYLIST,
|
||||||
Single.fromCallable(() ->
|
Single.fromCallable(() ->
|
||||||
PlaylistInfo.getInfo(NewPipe.getService(serviceId), url)));
|
PlaylistInfo.getInfo(NewPipe.getService(serviceId), url)));
|
||||||
}
|
}
|
||||||
|
@ -188,9 +190,10 @@ public final class ExtractorHelper {
|
||||||
PlaylistInfo.getMoreItems(NewPipe.getService(serviceId), url, nextPage));
|
PlaylistInfo.getMoreItems(NewPipe.getService(serviceId), url, nextPage));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Single<KioskInfo> getKioskInfo(final int serviceId, final String url,
|
public static Single<KioskInfo> getKioskInfo(final int serviceId,
|
||||||
|
final String url,
|
||||||
final boolean forceLoad) {
|
final boolean forceLoad) {
|
||||||
return checkCache(forceLoad, serviceId, url, InfoItem.InfoType.PLAYLIST,
|
return checkCache(forceLoad, serviceId, url, InfoCache.Type.KIOSK,
|
||||||
Single.fromCallable(() -> KioskInfo.getInfo(NewPipe.getService(serviceId), url)));
|
Single.fromCallable(() -> KioskInfo.getInfo(NewPipe.getService(serviceId), url)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +205,7 @@ public final class ExtractorHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Utils
|
// Cache
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -214,24 +217,25 @@ public final class ExtractorHelper {
|
||||||
* @param forceLoad whether to force loading from the network instead of from the cache
|
* @param forceLoad whether to force loading from the network instead of from the cache
|
||||||
* @param serviceId the service to load from
|
* @param serviceId the service to load from
|
||||||
* @param url the URL to load
|
* @param url the URL to load
|
||||||
* @param infoType the {@link InfoItem.InfoType} of the item
|
* @param cacheType the {@link InfoCache.Type} of the item
|
||||||
* @param loadFromNetwork the {@link Single} to load the item from the network
|
* @param loadFromNetwork the {@link Single} to load the item from the network
|
||||||
* @return a {@link Single} that loads the item
|
* @return a {@link Single} that loads the item
|
||||||
*/
|
*/
|
||||||
private static <I extends Info> Single<I> checkCache(final boolean forceLoad,
|
private static <I extends Info> Single<I> checkCache(final boolean forceLoad,
|
||||||
final int serviceId, final String url,
|
final int serviceId,
|
||||||
final InfoItem.InfoType infoType,
|
@NonNull final String url,
|
||||||
final Single<I> loadFromNetwork) {
|
@NonNull final InfoCache.Type cacheType,
|
||||||
|
@NonNull final Single<I> loadFromNetwork) {
|
||||||
checkServiceId(serviceId);
|
checkServiceId(serviceId);
|
||||||
final Single<I> actualLoadFromNetwork = loadFromNetwork
|
final Single<I> actualLoadFromNetwork = loadFromNetwork
|
||||||
.doOnSuccess(info -> CACHE.putInfo(serviceId, url, info, infoType));
|
.doOnSuccess(info -> CACHE.putInfo(serviceId, url, info, cacheType));
|
||||||
|
|
||||||
final Single<I> load;
|
final Single<I> load;
|
||||||
if (forceLoad) {
|
if (forceLoad) {
|
||||||
CACHE.removeInfo(serviceId, url, infoType);
|
CACHE.removeInfo(serviceId, url, cacheType);
|
||||||
load = actualLoadFromNetwork;
|
load = actualLoadFromNetwork;
|
||||||
} else {
|
} else {
|
||||||
load = Maybe.concat(ExtractorHelper.loadFromCache(serviceId, url, infoType),
|
load = Maybe.concat(ExtractorHelper.loadFromCache(serviceId, url, cacheType),
|
||||||
actualLoadFromNetwork.toMaybe())
|
actualLoadFromNetwork.toMaybe())
|
||||||
.firstElement() // Take the first valid
|
.firstElement() // Take the first valid
|
||||||
.toSingle();
|
.toSingle();
|
||||||
|
@ -246,15 +250,17 @@ public final class ExtractorHelper {
|
||||||
* @param <I> the item type's class that extends {@link Info}
|
* @param <I> the item type's class that extends {@link Info}
|
||||||
* @param serviceId the service to load from
|
* @param serviceId the service to load from
|
||||||
* @param url the URL to load
|
* @param url the URL to load
|
||||||
* @param infoType the {@link InfoItem.InfoType} of the item
|
* @param cacheType the {@link InfoCache.Type} of the item
|
||||||
* @return a {@link Single} that loads the item
|
* @return a {@link Single} that loads the item
|
||||||
*/
|
*/
|
||||||
private static <I extends Info> Maybe<I> loadFromCache(final int serviceId, final String url,
|
private static <I extends Info> Maybe<I> loadFromCache(
|
||||||
final InfoItem.InfoType infoType) {
|
final int serviceId,
|
||||||
|
@NonNull final String url,
|
||||||
|
@NonNull final InfoCache.Type cacheType) {
|
||||||
checkServiceId(serviceId);
|
checkServiceId(serviceId);
|
||||||
return Maybe.defer(() -> {
|
return Maybe.defer(() -> {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
final I info = (I) CACHE.getFromKey(serviceId, url, infoType);
|
final I info = (I) CACHE.getFromKey(serviceId, url, cacheType);
|
||||||
if (MainActivity.DEBUG) {
|
if (MainActivity.DEBUG) {
|
||||||
Log.d(TAG, "loadFromCache() called, info > " + info);
|
Log.d(TAG, "loadFromCache() called, info > " + info);
|
||||||
}
|
}
|
||||||
|
@ -268,11 +274,17 @@ public final class ExtractorHelper {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isCached(final int serviceId, final String url,
|
public static boolean isCached(final int serviceId,
|
||||||
final InfoItem.InfoType infoType) {
|
@NonNull final String url,
|
||||||
return null != loadFromCache(serviceId, url, infoType).blockingGet();
|
@NonNull final InfoCache.Type cacheType) {
|
||||||
|
return null != loadFromCache(serviceId, url, cacheType).blockingGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Utils
|
||||||
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats the text contained in the meta info list as HTML and puts it into the text view,
|
* Formats the text contained in the meta info list as HTML and puts it into the text view,
|
||||||
* while also making the separator visible. If the list is null or empty, or the user chose not
|
* while also making the separator visible. If the list is null or empty, or the user chose not
|
||||||
|
|
|
@ -27,7 +27,6 @@ import androidx.collection.LruCache;
|
||||||
|
|
||||||
import org.schabi.newpipe.MainActivity;
|
import org.schabi.newpipe.MainActivity;
|
||||||
import org.schabi.newpipe.extractor.Info;
|
import org.schabi.newpipe.extractor.Info;
|
||||||
import org.schabi.newpipe.extractor.InfoItem;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -48,14 +47,27 @@ public final class InfoCache {
|
||||||
// no instance
|
// no instance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies the type of {@link Info} to put into the cache.
|
||||||
|
*/
|
||||||
|
public enum Type {
|
||||||
|
STREAM,
|
||||||
|
CHANNEL,
|
||||||
|
CHANNEL_TAB,
|
||||||
|
COMMENTS,
|
||||||
|
PLAYLIST,
|
||||||
|
KIOSK,
|
||||||
|
}
|
||||||
|
|
||||||
public static InfoCache getInstance() {
|
public static InfoCache getInstance() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static String keyOf(final int serviceId, @NonNull final String url,
|
private static String keyOf(final int serviceId,
|
||||||
@NonNull final InfoItem.InfoType infoType) {
|
@NonNull final String url,
|
||||||
return serviceId + url + infoType.toString();
|
@NonNull final Type cacheType) {
|
||||||
|
return serviceId + ":" + cacheType.ordinal() + ":" + url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void removeStaleCache() {
|
private static void removeStaleCache() {
|
||||||
|
@ -83,19 +95,22 @@ public final class InfoCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Info getFromKey(final int serviceId, @NonNull final String url,
|
public Info getFromKey(final int serviceId,
|
||||||
@NonNull final InfoItem.InfoType infoType) {
|
@NonNull final String url,
|
||||||
|
@NonNull final Type cacheType) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "getFromKey() called with: "
|
Log.d(TAG, "getFromKey() called with: "
|
||||||
+ "serviceId = [" + serviceId + "], url = [" + url + "]");
|
+ "serviceId = [" + serviceId + "], url = [" + url + "]");
|
||||||
}
|
}
|
||||||
synchronized (LRU_CACHE) {
|
synchronized (LRU_CACHE) {
|
||||||
return getInfo(keyOf(serviceId, url, infoType));
|
return getInfo(keyOf(serviceId, url, cacheType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putInfo(final int serviceId, @NonNull final String url, @NonNull final Info info,
|
public void putInfo(final int serviceId,
|
||||||
@NonNull final InfoItem.InfoType infoType) {
|
@NonNull final String url,
|
||||||
|
@NonNull final Info info,
|
||||||
|
@NonNull final Type cacheType) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "putInfo() called with: info = [" + info + "]");
|
Log.d(TAG, "putInfo() called with: info = [" + info + "]");
|
||||||
}
|
}
|
||||||
|
@ -103,18 +118,19 @@ public final class InfoCache {
|
||||||
final long expirationMillis = ServiceHelper.getCacheExpirationMillis(info.getServiceId());
|
final long expirationMillis = ServiceHelper.getCacheExpirationMillis(info.getServiceId());
|
||||||
synchronized (LRU_CACHE) {
|
synchronized (LRU_CACHE) {
|
||||||
final CacheData data = new CacheData(info, expirationMillis);
|
final CacheData data = new CacheData(info, expirationMillis);
|
||||||
LRU_CACHE.put(keyOf(serviceId, url, infoType), data);
|
LRU_CACHE.put(keyOf(serviceId, url, cacheType), data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeInfo(final int serviceId, @NonNull final String url,
|
public void removeInfo(final int serviceId,
|
||||||
@NonNull final InfoItem.InfoType infoType) {
|
@NonNull final String url,
|
||||||
|
@NonNull final Type cacheType) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "removeInfo() called with: "
|
Log.d(TAG, "removeInfo() called with: "
|
||||||
+ "serviceId = [" + serviceId + "], url = [" + url + "]");
|
+ "serviceId = [" + serviceId + "], url = [" + url + "]");
|
||||||
}
|
}
|
||||||
synchronized (LRU_CACHE) {
|
synchronized (LRU_CACHE) {
|
||||||
LRU_CACHE.remove(keyOf(serviceId, url, infoType));
|
LRU_CACHE.remove(keyOf(serviceId, url, cacheType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue