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