1package com.bumptech.glide;
2
3import android.content.Context;
4import android.os.ParcelFileDescriptor;
5
6import com.bumptech.glide.load.model.ImageVideoModelLoader;
7import com.bumptech.glide.load.model.ImageVideoWrapper;
8import com.bumptech.glide.load.model.ModelLoader;
9import com.bumptech.glide.load.resource.drawable.GlideDrawable;
10import com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapper;
11import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
12import com.bumptech.glide.manager.Lifecycle;
13import com.bumptech.glide.manager.RequestTracker;
14import com.bumptech.glide.provider.DataLoadProvider;
15import com.bumptech.glide.provider.FixedLoadProvider;
16import com.bumptech.glide.request.FutureTarget;
17import com.bumptech.glide.request.target.Target;
18
19import java.io.File;
20import java.io.InputStream;
21
22/**
23 * A class for creating a load request that loads either an animated GIF drawable or a Bitmap drawable directly, or
24 * adds an {@link com.bumptech.glide.load.resource.transcode.ResourceTranscoder} to transcode the data into a
25 * resource type other than a {@link android.graphics.drawable.Drawable}.
26 *
27 * @param  The type of model to use to load the {@link android.graphics.drawable.BitmapDrawable} or
28 * {@link com.bumptech.glide.load.resource.gif.GifDrawable}.
29 */
30public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> implements DownloadOptions {
31    private final ModelLoader<ModelType, InputStream> streamModelLoader;
32    private final ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader;
33    private final RequestManager.OptionsApplier optionsApplier;
34
35    private static <A, Z, R> FixedLoadProvider<A, ImageVideoWrapper, Z, R> buildProvider(Glide glide,
36            ModelLoader<A, InputStream> streamModelLoader,
37            ModelLoader<A, ParcelFileDescriptor> fileDescriptorModelLoader, Class<Z> resourceClass,
38            Class<R> transcodedClass,
39            ResourceTranscoder<Z, R> transcoder) {
40        if (streamModelLoader == null && fileDescriptorModelLoader == null) {
41            return null;
42        }
43
44        if (transcoder == null) {
45            transcoder = glide.buildTranscoder(resourceClass, transcodedClass);
46        }
47        DataLoadProvider<ImageVideoWrapper, Z> dataLoadProvider = glide.buildDataProvider(ImageVideoWrapper.class,
48                resourceClass);
49        ImageVideoModelLoader<A> modelLoader = new ImageVideoModelLoader<A>(streamModelLoader,
50                fileDescriptorModelLoader);
51        return new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider);
52    }
53
54    DrawableTypeRequest(Class<ModelType> modelClass, ModelLoader<ModelType, InputStream> streamModelLoader,
55            ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader, Context context, Glide glide,
56            RequestTracker requestTracker, Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
57        super(context, modelClass,
58                buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, GifBitmapWrapper.class,
59                        GlideDrawable.class, null),
60                glide, requestTracker, lifecycle);
61        this.streamModelLoader = streamModelLoader;
62        this.fileDescriptorModelLoader = fileDescriptorModelLoader;
63        this.optionsApplier = optionsApplier;
64    }
65
66    /**
67     * Attempts to always load the resource as a {@link android.graphics.Bitmap}, even if it could actually be animated.
68     *
69     * @return A new request builder for loading a {@link android.graphics.Bitmap}
70     */
71    public BitmapTypeRequest<ModelType> asBitmap() {
72        return optionsApplier.apply(new BitmapTypeRequest<ModelType>(this, streamModelLoader,
73                fileDescriptorModelLoader, optionsApplier));
74    }
75
76    /**
77     * Attempts to always load the resource as a {@link com.bumptech.glide.load.resource.gif.GifDrawable}.
78     * <p>
79     *     If the underlying data is not a GIF, this will fail. As a result, this should only be used if the model
80     *     represents an animated GIF and the caller wants to interact with the GIfDrawable directly. Normally using
81     *     just an {@link com.bumptech.glide.DrawableTypeRequest} is sufficient because it will determine whether or
82     *     not the given data represents an animated GIF and return the appropriate animated or not animated
83     *     {@link android.graphics.drawable.Drawable} automatically.
84     * </p>
85     *
86     * @return A new request builder for loading a {@link com.bumptech.glide.load.resource.gif.GifDrawable}.
87     */
88    public GifTypeRequest<ModelType> asGif() {
89        return optionsApplier.apply(new GifTypeRequest<ModelType>(this, streamModelLoader, optionsApplier));
90    }
91
92    /**
93     * {@inheritDoc}
94     */
95    public <Y extends Target<File>> Y downloadOnly(Y target) {
96        return getDownloadOnlyRequest().downloadOnly(target);
97    }
98
99    /**
100     * {@inheritDoc}
101     */
102    public FutureTarget<File> downloadOnly(int width, int height) {
103        return getDownloadOnlyRequest().downloadOnly(width, height);
104    }
105
106    private GenericTranscodeRequest<ModelType, InputStream, File> getDownloadOnlyRequest() {
107        return optionsApplier.apply(new GenericTranscodeRequest<ModelType, InputStream, File>(File.class, this,
108                streamModelLoader, InputStream.class, File.class, optionsApplier));
109    }
110}
111