EngineJob.java revision e743a1f03f24e33270f38de883b508d4312a7f69
1package com.bumptech.glide.load.engine;
2
3import android.os.Handler;
4import android.util.Log;
5import com.bumptech.glide.Resource;
6import com.bumptech.glide.load.Key;
7import com.bumptech.glide.request.ResourceCallback;
8import com.bumptech.glide.util.LogTime;
9
10import java.util.ArrayList;
11import java.util.List;
12
13public class EngineJob implements ResourceCallback {
14    private static final String TAG = "EngineJob";
15    private boolean isCacheable;
16    private final EngineJobListener listener;
17    private Key key;
18    private Handler mainHandler;
19    private List<ResourceCallback> cbs;
20    private ResourceCallback cb;
21    private boolean isCancelled;
22    private boolean isComplete;
23
24    public EngineJob(Key key, Handler mainHandler, boolean isCacheable, EngineJobListener listener) {
25        this.key = key;
26        this.isCacheable = isCacheable;
27        this.listener = listener;
28        this.mainHandler = mainHandler;
29    }
30
31    public void addCallback(ResourceCallback cb) {
32        if (this.cb == null) {
33            this.cb = cb;
34        } else {
35            if (cbs == null) {
36                cbs = new ArrayList<ResourceCallback>(2);
37                cbs.add(this.cb);
38            }
39            cbs.add(cb);
40        }
41    }
42
43    public void removeCallback(ResourceCallback cb) {
44        if (cbs != null) {
45            cbs.remove(cb);
46            if (cbs.size() == 0) {
47                cancel();
48            }
49        } else if (this.cb == cb) {
50            this.cb = null;
51            cancel();
52        }
53    }
54
55    // Exposed for testing.
56    void cancel() {
57        if (isComplete || isCancelled) {
58            return;
59        }
60        isCancelled = true;
61        listener.onEngineJobCancelled(key);
62    }
63
64    // Exposed for testing.
65    boolean isCancelled() {
66        return isCancelled;
67    }
68
69    @Override
70    public void onResourceReady(final Resource resource) {
71        final long start = LogTime.getLogTime();
72        mainHandler.post(new Runnable() {
73            @Override
74            public void run() {
75                if (Log.isLoggable(TAG, Log.VERBOSE)) {
76                    Log.v(TAG, "Posted to main thread in onResourceReady in " + LogTime.getElapsedMillis(start)
77                            + " cancelled: " + isCancelled);
78                }
79                if (isCancelled) {
80                    resource.recycle();
81                    return;
82                }
83                resource.setCacheable(isCacheable);
84                isComplete = true;
85
86                // Hold on to resource for duration of request so we don't recycle it in the middle of notifying if it
87                // synchronously released by one of the callbacks.
88                resource.acquire(1);
89                listener.onEngineJobComplete(key, resource);
90                if (cbs != null) {
91                    resource.acquire(cbs.size());
92                    for (ResourceCallback cb : cbs) {
93                        cb.onResourceReady(resource);
94                    }
95                } else {
96                    resource.acquire(1);
97                    cb.onResourceReady(resource);
98                }
99                // Our request is complete, so we can release the resource.
100                resource.release();
101                if (Log.isLoggable(TAG, Log.VERBOSE)) {
102                    Log.v(TAG, "Finished resource ready in " + LogTime.getElapsedMillis(start));
103                }
104            }
105        });
106    }
107
108    @Override
109    public void onException(final Exception e) {
110        final long start = LogTime.getLogTime();
111        mainHandler.post(new Runnable() {
112            @Override
113            public void run() {
114                if (Log.isLoggable(TAG, Log.VERBOSE)) {
115                    Log.v(TAG, "posted to main thread in onException in " + LogTime.getElapsedMillis(start)
116                            + " cancelled: " + isCancelled);
117                }
118                if (isCancelled) {
119                    return;
120                }
121                isComplete = true;
122
123                listener.onEngineJobComplete(key, null);
124                if (cbs != null) {
125                    for (ResourceCallback cb : cbs) {
126                        cb.onException(e);
127                    }
128                } else {
129                    cb.onException(e);
130                }
131                if (Log.isLoggable(TAG, Log.VERBOSE)) {
132                    Log.v(TAG, "finished onException in " + LogTime.getElapsedMillis(start));
133                }
134            }
135        });
136    }
137}
138