1package com.bumptech.glide.load.engine;
2
3import android.os.SystemClock;
4import android.util.Log;
5import com.bumptech.glide.load.CacheLoader;
6import com.bumptech.glide.Priority;
7import com.bumptech.glide.load.ResourceDecoder;
8import com.bumptech.glide.load.Transformation;
9import com.bumptech.glide.load.engine.executor.Prioritized;
10import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
11
12import java.io.InputStream;
13import java.util.concurrent.ExecutorService;
14import java.util.concurrent.Future;
15
16/**
17 *
18 * @param <Z> The type of the resource that will be decoded.
19 * @param <R> the type of the resource the decoded resource will be transcoded to.
20 */
21public class ResourceRunner<Z, R> implements Runnable, Prioritized {
22    private static final String TAG = "ResourceRunner";
23
24    private final EngineKey key;
25    private final Transformation<Z> transformation;
26    private final ResourceTranscoder<Z, R> transcoder;
27    private final SourceResourceRunner sourceRunner;
28    private final EngineJob job;
29    private final Priority priority;
30    private final ResourceDecoder<InputStream, Z> cacheDecoder;
31    private final int width;
32    private final int height;
33    private final CacheLoader cacheLoader;
34    private final ExecutorService diskCacheService;
35    private final ExecutorService resizeService;
36    private volatile Future<?> future;
37    private volatile boolean isCancelled;
38
39    public ResourceRunner(EngineKey key, int width, int height, CacheLoader cacheLoader,
40            ResourceDecoder<InputStream, Z> cacheDecoder, Transformation<Z> transformation,
41            ResourceTranscoder<Z, R> transcoder, SourceResourceRunner sourceRunner, ExecutorService diskCacheService,
42            ExecutorService resizeService, EngineJob job, Priority priority) {
43        this.key = key;
44        this.width = width;
45        this.height = height;
46        this.cacheLoader = cacheLoader;
47        this.cacheDecoder = cacheDecoder;
48        this.transformation = transformation;
49        this.transcoder = transcoder;
50        this.sourceRunner = sourceRunner;
51        this.diskCacheService = diskCacheService;
52        this.resizeService = resizeService;
53        this.job = job;
54        this.priority = priority;
55    }
56
57    public EngineJob getJob() {
58        return job;
59    }
60
61    public void cancel() {
62        isCancelled = true;
63        if (future != null) {
64            future.cancel(false);
65        }
66        sourceRunner.cancel();
67    }
68
69    public void queue() {
70        future = diskCacheService.submit(this);
71    }
72
73    @Override
74    public void run() {
75        if (isCancelled) {
76            return;
77        }
78
79        long start = SystemClock.currentThreadTimeMillis();
80        Resource<Z> fromCache = cacheLoader.load(key, cacheDecoder, width, height);
81        if (Log.isLoggable(TAG, Log.VERBOSE)) {
82            Log.v(TAG, "loaded from disk cache in " + (SystemClock.currentThreadTimeMillis() - start));
83        }
84        if (fromCache != null) {
85            Resource<Z> transformed = transformation.transform(fromCache, width, height);
86            if (transformed != fromCache) {
87                fromCache.recycle();
88            }
89            Resource<R> transcoded = transcoder.transcode(transformed);
90            job.onResourceReady(transcoded);
91        } else {
92            future = resizeService.submit(sourceRunner);
93        }
94    }
95
96    @Override
97    public int getPriority() {
98        return priority.ordinal();
99    }
100}
101