Skip to content

Commit

Permalink
Add isAlternateCacheKey to a new ExperimentalRequestListener interface.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 319301011
  • Loading branch information
sjudd authored and glide-copybara-robot committed Jul 1, 2020
1 parent 85868bd commit d84034d
Show file tree
Hide file tree
Showing 10 changed files with 195 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class DecodeJob<R>
private volatile DataFetcherGenerator currentGenerator;
private volatile boolean isCallbackNotified;
private volatile boolean isCancelled;
private boolean isLoadingFromAlternateCacheKey;

DecodeJob(DiskCacheProvider diskCacheProvider, Pools.Pool<DecodeJob<?>> pool) {
this.diskCacheProvider = diskCacheProvider;
Expand Down Expand Up @@ -332,9 +333,10 @@ private void notifyFailed() {
onLoadFailed();
}

private void notifyComplete(Resource<R> resource, DataSource dataSource) {
private void notifyComplete(
Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
setNotifiedOrThrow();
callback.onResourceReady(resource, dataSource);
callback.onResourceReady(resource, dataSource, isLoadedFromAlternateCacheKey);
}

private void setNotifiedOrThrow() {
Expand Down Expand Up @@ -381,6 +383,8 @@ public void onDataFetcherReady(
this.currentFetcher = fetcher;
this.currentDataSource = dataSource;
this.currentAttemptingKey = attemptedKey;
this.isLoadingFromAlternateCacheKey = sourceKey != decodeHelper.getCacheKeys().get(0);

if (Thread.currentThread() != currentThread) {
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
Expand Down Expand Up @@ -429,13 +433,14 @@ private void decodeFromRetrievedData() {
throwables.add(e);
}
if (resource != null) {
notifyEncodeAndRelease(resource, currentDataSource);
notifyEncodeAndRelease(resource, currentDataSource, isLoadingFromAlternateCacheKey);
} else {
runGenerators();
}
}

private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
private void notifyEncodeAndRelease(
Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
if (resource instanceof Initializable) {
((Initializable) resource).initialize();
}
Expand All @@ -447,7 +452,7 @@ private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource)
result = lockedResource;
}

notifyComplete(result, dataSource);
notifyComplete(result, dataSource, isLoadedFromAlternateCacheKey);

stage = Stage.ENCODE;
try {
Expand Down Expand Up @@ -710,7 +715,8 @@ void clear() {

interface Callback<R> {

void onResourceReady(Resource<R> resource, DataSource dataSource);
void onResourceReady(
Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey);

void onLoadFailed(GlideException e);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ public <R> LoadStatus load(

// Avoid calling back while holding the engine lock, doing so makes it easier for callers to
// deadlock.
cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
cb.onResourceReady(
memoryResource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class EngineJob<R> implements DecodeJob.Callback<R>, Poolable {

// Checked primarily on the main thread, but also on other threads in reschedule.
private volatile boolean isCancelled;
private boolean isLoadedFromAlternateCacheKey;

EngineJob(
GlideExecutor diskCacheExecutor,
Expand Down Expand Up @@ -155,7 +156,7 @@ void callCallbackOnResourceReady(ResourceCallback cb) {
// This is overly broad, some Glide code is actually called here, but it's much
// simpler to encapsulate here than to do so at the actual call point in the
// Request implementation.
cb.onResourceReady(engineResource, dataSource);
cb.onResourceReady(engineResource, dataSource, isLoadedFromAlternateCacheKey);
} catch (Throwable t) {
throw new CallbackException(t);
}
Expand Down Expand Up @@ -304,6 +305,7 @@ private synchronized void release() {
hasLoadFailed = false;
isCancelled = false;
hasResource = false;
isLoadedFromAlternateCacheKey = false;
decodeJob.release(/*isRemovedFromQueue=*/ false);
decodeJob = null;
exception = null;
Expand All @@ -312,10 +314,12 @@ private synchronized void release() {
}

@Override
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
public void onResourceReady(
Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
this.isLoadedFromAlternateCacheKey = isLoadedFromAlternateCacheKey;
}
notifyCallbacksOfResult();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.bumptech.glide.request;

import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.request.target.Target;

/**
* An extension of {@link RequestListener} with additional parameters.
*
* <p>All equivalent methods are called at the relevant time by Glide. Implementations therefore
* should only implement one version of each method.
*
* @param <ResourceT> The type of resource that will be loaded for the request.
* @deprecated Not ready for public consumption, avoid using this class. It may be removed at any
* time.
*/
@Deprecated
public abstract class ExperimentalRequestListener<ResourceT> implements RequestListener<ResourceT> {

/**
* Identical to {@link #onResourceReady(Object, Object, Target, DataSource, boolean)} except that
* {@code isAlternateCacheKey} is provided.
*
* @param isAlternateCacheKey True if the data was obtained from the disk cache using an alternate
* cache key provided by a {@link com.bumptech.glide.load.model.ModelLoader} via {@link
* com.bumptech.glide.load.model.ModelLoader.LoadData#alternateKeys}. Valid only if {@code
* dataSource} is {@link DataSource#DATA_DISK_CACHE} or {@link
* DataSource#RESOURCE_DISK_CACHE}.
*/
public abstract boolean onResourceReady(
ResourceT resource,
Object model,
Target<ResourceT> target,
DataSource dataSource,
boolean isFirstResource,
boolean isAlternateCacheKey);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public interface ResourceCallback {
*
* @param resource The loaded resource.
*/
void onResourceReady(Resource<?> resource, DataSource dataSource);
void onResourceReady(
Resource<?> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey);

/**
* Called when a resource fails to load successfully.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,8 @@ public void begin() {
// that the view size has changed will need to explicitly clear the View or Target before
// starting the new load.
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
onResourceReady(
resource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
return;
}

Expand Down Expand Up @@ -520,7 +521,8 @@ private void notifyLoadFailed() {
/** A callback method that should never be invoked directly. */
@SuppressWarnings("unchecked")
@Override
public void onResourceReady(Resource<?> resource, DataSource dataSource) {
public void onResourceReady(
Resource<?> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
stateVerifier.throwIfRecycled();
Resource<?> toRelease = null;
try {
Expand Down Expand Up @@ -572,7 +574,8 @@ public void onResourceReady(Resource<?> resource, DataSource dataSource) {
return;
}

onResourceReady((Resource<R>) resource, (R) received, dataSource);
onResourceReady(
(Resource<R>) resource, (R) received, dataSource, isLoadedFromAlternateCacheKey);
}
} finally {
if (toRelease != null) {
Expand All @@ -582,14 +585,18 @@ public void onResourceReady(Resource<?> resource, DataSource dataSource) {
}

/**
* Internal {@link #onResourceReady(Resource, DataSource)} where arguments are known to be safe.
* Internal {@link #onResourceReady(Resource, DataSource, boolean)} where arguments are known to
* be safe.
*
* @param resource original {@link Resource}, never <code>null</code>
* @param result object returned by {@link Resource#get()}, checked for type and never <code>null
* </code>
*/
// We're using experimental APIs...
@SuppressWarnings({"deprecation", "PMD.UnusedFormalParameter"})
@GuardedBy("requestLock")
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
private void onResourceReady(
Resource<R> resource, R result, DataSource dataSource, boolean isAlternateCacheKey) {
// We must call isFirstReadyResource before setting status.
boolean isFirstResource = isFirstReadyResource();
status = Status.COMPLETE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,12 @@ public void runTest() {
public void testMultipleRequestListeners() {
getNullModelRequest().addListener(listener1).addListener(listener2).into(target);
verify(requestManager).track(any(Target.class), requestCaptor.capture());
requestCaptor.getValue().onResourceReady(new SimpleResource<>(new Object()), DataSource.LOCAL);
requestCaptor
.getValue()
.onResourceReady(
new SimpleResource<>(new Object()),
DataSource.LOCAL,
/*isLoadedFromAlternateCacheKey=*/ false);

verify(listener1)
.onResourceReady(any(), any(), isA(Target.class), isA(DataSource.class), anyBoolean());
Expand All @@ -140,7 +145,12 @@ public void testMultipleRequestListeners() {
public void testListenerApiOverridesListeners() {
getNullModelRequest().addListener(listener1).listener(listener2).into(target);
verify(requestManager).track(any(Target.class), requestCaptor.capture());
requestCaptor.getValue().onResourceReady(new SimpleResource<>(new Object()), DataSource.LOCAL);
requestCaptor
.getValue()
.onResourceReady(
new SimpleResource<>(new Object()),
DataSource.LOCAL,
/*isLoadedFromAlternateCacheKey=*/ false);

// The #listener API removes any previous listeners, so the first listener should not be called.
verify(listener1, never())
Expand Down
Loading

0 comments on commit d84034d

Please sign in to comment.