Merge pull request #10717 from Stypox/cache-key-type

Calculate cache key based on info type instead of item type
This commit is contained in:
Stypox 2024-03-28 13:34:51 +01:00 committed by GitHub
commit e0268a91ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 69 additions and 41 deletions

View File

@ -198,7 +198,7 @@ dependencies {
// name and the commit hash with the commit hash of the (pushed) commit you want to test // name and the commit hash with the commit hash of the (pushed) commit you want to test
// This works thanks to JitPack: https://jitpack.io/ // This works thanks to JitPack: https://jitpack.io/
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751' implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.23.1' implementation 'com.github.Stypox:NewPipeExtractor:aaf3231fc75d7b4177549fec4aa7e672bfe84015'
implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0' implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0'
/** Checkstyle **/ /** Checkstyle **/

View File

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

View File

@ -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

View File

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