All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bumptech.glide.load.model.MultiModelLoader Maven / Gradle / Ivy

Go to download

A fast and efficient image loading library for Android focused on smooth scrolling.

There is a newer version: 5.0.0-rc01
Show newest version
package com.bumptech.glide.load.model;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Pools.Pool;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.data.DataFetcher.DataCallback;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.util.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Allows attempting multiple ModelLoaders registered for a given model and data class.
 *
 * 

TODO: we should try to find a way to remove this class. It exists to allow individual * ModelLoaders to delegate to multiple ModelLoaders without having to duplicate this logic * everywhere. We have very similar logic in the {@link * com.bumptech.glide.load.engine.DataFetcherGenerator} implementations and should try to avoid this * duplication. */ class MultiModelLoader implements ModelLoader { private final List> modelLoaders; private final Pool> exceptionListPool; MultiModelLoader( @NonNull List> modelLoaders, @NonNull Pool> exceptionListPool) { this.modelLoaders = modelLoaders; this.exceptionListPool = exceptionListPool; } @Override public LoadData buildLoadData( @NonNull Model model, int width, int height, @NonNull Options options) { Key sourceKey = null; int size = modelLoaders.size(); List> fetchers = new ArrayList<>(size); //noinspection ForLoopReplaceableByForEach to improve perf for (int i = 0; i < size; i++) { ModelLoader modelLoader = modelLoaders.get(i); if (modelLoader.handles(model)) { LoadData loadData = modelLoader.buildLoadData(model, width, height, options); if (loadData != null) { sourceKey = loadData.sourceKey; fetchers.add(loadData.fetcher); } } } return !fetchers.isEmpty() && sourceKey != null ? new LoadData<>(sourceKey, new MultiFetcher<>(fetchers, exceptionListPool)) : null; } @Override public boolean handles(@NonNull Model model) { for (ModelLoader modelLoader : modelLoaders) { if (modelLoader.handles(model)) { return true; } } return false; } @Override public String toString() { return "MultiModelLoader{" + "modelLoaders=" + Arrays.toString(modelLoaders.toArray()) + '}'; } static class MultiFetcher implements DataFetcher, DataCallback { private final List> fetchers; private final Pool> throwableListPool; private int currentIndex; private Priority priority; private DataCallback callback; @Nullable private List exceptions; private boolean isCancelled; MultiFetcher( @NonNull List> fetchers, @NonNull Pool> throwableListPool) { this.throwableListPool = throwableListPool; Preconditions.checkNotEmpty(fetchers); this.fetchers = fetchers; currentIndex = 0; } @Override public void loadData(@NonNull Priority priority, @NonNull DataCallback callback) { this.priority = priority; this.callback = callback; exceptions = throwableListPool.acquire(); fetchers.get(currentIndex).loadData(priority, this); // If a race occurred where we cancelled the fetcher in cancel() and then called loadData here // immediately after, make sure that we cancel the newly started fetcher. We don't bother // checking cancelled before loadData because it's not required for correctness and would // require an unlikely race to be useful. if (isCancelled) { cancel(); } } @Override public void cleanup() { if (exceptions != null) { throwableListPool.release(exceptions); } exceptions = null; for (DataFetcher fetcher : fetchers) { fetcher.cleanup(); } } @Override public void cancel() { isCancelled = true; for (DataFetcher fetcher : fetchers) { fetcher.cancel(); } } @NonNull @Override public Class getDataClass() { return fetchers.get(0).getDataClass(); } @NonNull @Override public DataSource getDataSource() { return fetchers.get(0).getDataSource(); } @Override public void onDataReady(@Nullable Data data) { if (data != null) { callback.onDataReady(data); } else { startNextOrFail(); } } @Override public void onLoadFailed(@NonNull Exception e) { Preconditions.checkNotNull(exceptions).add(e); startNextOrFail(); } private void startNextOrFail() { if (isCancelled) { return; } if (currentIndex < fetchers.size() - 1) { currentIndex++; loadData(priority, callback); } else { Preconditions.checkNotNull(exceptions); callback.onLoadFailed(new GlideException("Fetch failed", new ArrayList<>(exceptions))); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy