com.bumptech.glide.load.engine.SourceGenerator Maven / Gradle / Ivy
Show all versions of glide Show documentation
package com.bumptech.glide.load.engine;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.Encoder;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.data.DataFetcher.DataCallback;
import com.bumptech.glide.load.data.DataRewinder;
import com.bumptech.glide.load.engine.cache.DiskCache;
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.model.ModelLoader.LoadData;
import com.bumptech.glide.util.LogTime;
import com.bumptech.glide.util.Synthetic;
import java.io.IOException;
import java.util.Collections;
/**
* Generates {@link com.bumptech.glide.load.data.DataFetcher DataFetchers} from original source data
* using registered {@link com.bumptech.glide.load.model.ModelLoader ModelLoaders} and the model
* provided for the load.
*
* Depending on the disk cache strategy, source data may first be written to disk and then loaded
* from the cache file rather than returned directly.
*
*
This object may be used by multiple threads, but only one at a time. It is not safe to access
* this object on multiple threads concurrently.
*/
class SourceGenerator implements DataFetcherGenerator, DataFetcherGenerator.FetcherReadyCallback {
private static final String TAG = "SourceGenerator";
private final DecodeHelper> helper;
private final FetcherReadyCallback cb;
private volatile int loadDataListIndex;
private volatile DataCacheGenerator sourceCacheGenerator;
private volatile Object dataToCache;
private volatile ModelLoader.LoadData> loadData;
private volatile DataCacheKey originalKey;
SourceGenerator(DecodeHelper> helper, FetcherReadyCallback cb) {
this.helper = helper;
this.cb = cb;
}
// Concurrent access isn't supported.
@SuppressWarnings({"NonAtomicOperationOnVolatileField", "NonAtomicVolatileUpdate"})
@Override
public boolean startNext() {
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
try {
boolean isDataInCache = cacheData(data);
// If we failed to write the data to cache, the cacheData method will try to decode the
// original data directly instead of going through the disk cache. Since cacheData has
// already called our callback at this point, there's nothing more to do but return.
if (!isDataInCache) {
return true;
}
// If we were able to write the data to cache successfully, we now need to proceed to call
// the sourceCacheGenerator below to load the data from cache.
} catch (IOException e) {
// An IOException means we weren't able to write data to cache or we weren't able to rewind
// it after a disk cache write failed. In either case we can just move on and try the next
// fetch below.
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Failed to properly rewind or write data to cache", e);
}
}
}
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
sourceCacheGenerator = null;
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
startNextLoad(loadData);
}
}
return started;
}
private void startNextLoad(final LoadData> toStart) {
loadData.fetcher.loadData(
helper.getPriority(),
new DataCallback