• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.bumptech.glide.load.engine;
2 
3 import android.util.Log;
4 
5 import com.bumptech.glide.Priority;
6 import com.bumptech.glide.load.engine.executor.Prioritized;
7 import com.bumptech.glide.request.ResourceCallback;
8 
9 /**
10  * A runnable class responsible for using an {@link com.bumptech.glide.load.engine.DecodeJob} to decode resources on a
11  * background thread in two stages.
12  *
13  * <p>
14  *     In the first stage, this class attempts to decode a resource
15  *     from cache, first using transformed data and then using source data. If no resource can be decoded from cache,
16  *     this class then requests to be posted again. During the second stage this class then attempts to use the
17  *     {@link com.bumptech.glide.load.engine.DecodeJob} to decode data directly from the original source.
18  * </p>
19  *
20  * <p>
21  *     Using two stages with a re-post in between allows us to run fast disk cache decodes on one thread and slow source
22  *     fetches on a second pool so that loads for local data are never blocked waiting for loads for remote data to
23  *     complete.
24  * </p>
25  */
26 class EngineRunnable implements Runnable, Prioritized {
27     private static final String TAG = "EngineRunnable";
28 
29     private final Priority priority;
30     private final EngineRunnableManager manager;
31     private final DecodeJob<?, ?, ?> decodeJob;
32 
33     private Stage stage;
34 
35     private volatile boolean isCancelled;
36 
EngineRunnable(EngineRunnableManager manager, DecodeJob<?, ?, ?> decodeJob, Priority priority)37     public EngineRunnable(EngineRunnableManager manager, DecodeJob<?, ?, ?> decodeJob, Priority priority) {
38         this.manager = manager;
39         this.decodeJob = decodeJob;
40         this.stage = Stage.CACHE;
41         this.priority = priority;
42     }
43 
cancel()44     public void cancel() {
45         isCancelled = true;
46         decodeJob.cancel();
47     }
48 
49     @Override
run()50     public void run() {
51         if (isCancelled) {
52             return;
53         }
54 
55         Exception exception = null;
56         Resource<?> resource = null;
57         try {
58             resource = decode();
59         } catch (Exception e) {
60             if (Log.isLoggable(TAG, Log.VERBOSE)) {
61                 Log.v(TAG, "Exception decoding", e);
62             }
63             exception = e;
64         }
65 
66         if (isCancelled) {
67             if (resource != null) {
68                 resource.recycle();
69             }
70             return;
71         }
72 
73         if (resource == null) {
74             onLoadFailed(exception);
75         } else {
76             onLoadComplete(resource);
77         }
78     }
79 
isDecodingFromCache()80     private boolean isDecodingFromCache() {
81         return stage == Stage.CACHE;
82     }
83 
onLoadComplete(Resource resource)84     private void onLoadComplete(Resource resource) {
85         manager.onResourceReady(resource);
86     }
87 
onLoadFailed(Exception e)88     private void onLoadFailed(Exception e) {
89         if (isDecodingFromCache()) {
90             stage = Stage.SOURCE;
91             manager.submitForSource(this);
92         } else {
93             manager.onException(e);
94         }
95     }
96 
decode()97     private Resource<?> decode() throws Exception {
98         if (isDecodingFromCache()) {
99             return decodeFromCache();
100         } else {
101             return decodeFromSource();
102         }
103     }
104 
decodeFromCache()105     private Resource<?> decodeFromCache() throws Exception {
106         Resource<?> result = null;
107         try {
108             result = decodeJob.decodeResultFromCache();
109         } catch (Exception e) {
110             if (Log.isLoggable(TAG, Log.DEBUG)) {
111                 Log.d(TAG, "Exception decoding result from cache: " + e);
112             }
113         }
114 
115         if (result == null) {
116             result = decodeJob.decodeSourceFromCache();
117         }
118         return result;
119     }
120 
decodeFromSource()121     private Resource<?> decodeFromSource() throws Exception {
122         return decodeJob.decodeFromSource();
123     }
124 
125     @Override
getPriority()126     public int getPriority() {
127         return priority.ordinal();
128     }
129 
130     private enum Stage {
131         /** Attempting to decode resource from cache. */
132         CACHE,
133         /** Attempting to decode resource from source data. */
134         SOURCE
135     }
136 
137     interface EngineRunnableManager extends ResourceCallback {
submitForSource(EngineRunnable runnable)138         void submitForSource(EngineRunnable runnable);
139     }
140 }
141