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