GenericRequest.java revision 1a0d2f25951a536b465c5b2a1dfa5d3c076de912
1package com.bumptech.glide.request; 2 3import android.content.Context; 4import android.graphics.drawable.Drawable; 5import android.util.Log; 6import android.view.animation.Animation; 7import android.view.animation.AnimationUtils; 8import com.bumptech.glide.Priority; 9import com.bumptech.glide.Resource; 10import com.bumptech.glide.load.ResourceDecoder; 11import com.bumptech.glide.load.ResourceEncoder; 12import com.bumptech.glide.load.Transformation; 13import com.bumptech.glide.load.resource.transcode.ResourceTranscoder; 14import com.bumptech.glide.load.engine.Engine; 15import com.bumptech.glide.load.model.ModelLoader; 16import com.bumptech.glide.load.data.DataFetcher; 17import com.bumptech.glide.provider.LoadProvider; 18import com.bumptech.glide.request.target.Target; 19 20import java.io.InputStream; 21 22/** 23 * A {@link Request} that loads a {@link Resource} into a given {@link Target}. 24 * 25 * @param <A> The type of the model that the resource will be loaded from. 26 * @param <T> The type of the data that the resource will be loaded from. 27 * @param <Z> The type of the resource that will be loaded. 28 */ 29public class GenericRequest<A, T, Z, R> implements Request, Target.SizeReadyCallback, ResourceCallback { 30 private static final String TAG = "Request"; 31 32 private final int placeholderResourceId; 33 private final int errorResourceId; 34 private final Context context; 35 private final Transformation<Z> transformation; 36 private final LoadProvider<A, T, Z, R> loadProvider; 37 private final int animationId; 38 private final RequestCoordinator requestCoordinator; 39 private final A model; 40 private Class<R> transcodeClass; 41 private boolean isMemoryCacheable; 42 private Priority priority; 43 private final Target<R> target; 44 private final RequestListener<A> requestListener; 45 private final float sizeMultiplier; 46 private final Engine engine; 47 private Animation animation; 48 private Drawable placeholderDrawable; 49 private Drawable errorDrawable; 50 private boolean isCancelled; 51 private boolean isError; 52 private boolean loadedFromMemoryCache; 53 private Resource resource; 54 private Engine.LoadStatus loadStatus; 55 56 public GenericRequest(LoadProvider<A, T, Z, R> loadProvider, A model, Context context, Priority priority, 57 Target<R> target, float sizeMultiplier, Drawable placeholderDrawable, int placeholderResourceId, 58 Drawable errorDrawable, int errorResourceId, RequestListener<A> requestListener, int animationId, 59 Animation animation, RequestCoordinator requestCoordinator, Engine engine, 60 Transformation<Z> transformation, Class<R> transcodeClass, boolean isMemoryCacheable) { 61 this.loadProvider = loadProvider; 62 this.model = model; 63 this.context = context; 64 this.priority = priority; 65 this.target = target; 66 this.sizeMultiplier = sizeMultiplier; 67 this.placeholderDrawable = placeholderDrawable; 68 this.placeholderResourceId = placeholderResourceId; 69 this.errorDrawable = errorDrawable; 70 this.errorResourceId = errorResourceId; 71 this.requestListener = requestListener; 72 this.animationId = animationId; 73 this.animation = animation; 74 this.requestCoordinator = requestCoordinator; 75 this.engine = engine; 76 this.transformation = transformation; 77 this.transcodeClass = transcodeClass; 78 this.isMemoryCacheable = isMemoryCacheable; 79 80 // We allow null models by just setting an error drawable. Null models will always have empty providers, we 81 // simply skip our sanity checks in that unusual case. 82 if (model != null) { 83 if (loadProvider.getCacheDecoder() == null) { 84 throw new NullPointerException("CacheDecoder must not be null, try .cacheDecoder(ResouceDecoder)"); 85 } 86 if (loadProvider.getSourceDecoder() == null) { 87 throw new NullPointerException("SourceDecoder must not be null, try .imageDecoder(ResourceDecoder) " + 88 "and/or .videoDecoder()"); 89 } 90 if (loadProvider.getEncoder() == null) { 91 throw new NullPointerException("Encoder must not be null, try .encode(ResourceEncoder)"); 92 } 93 if (loadProvider.getTranscoder() == null) { 94 throw new NullPointerException("Transcoder must not be null, try .as(Class, ResourceTranscoder)"); 95 } 96 if (loadProvider.getModelLoader() == null) { 97 throw new NullPointerException("ModelLoader must not be null, try .using(ModelLoader)"); 98 } 99 } 100 } 101 102 @Override 103 public void run() { 104 if (model == null) { 105 onException(null); 106 return; 107 } 108 109 target.getSize(this); 110 111 if (!isComplete() && !isFailed()) { 112 setPlaceHolder(); 113 } 114 } 115 116 public void cancel() { 117 isCancelled = true; 118 if (loadStatus != null) { 119 loadStatus.cancel(); 120 loadStatus = null; 121 } 122 } 123 124 @Override 125 public void clear() { 126 cancel(); 127 setPlaceHolder(); 128 if (resource != null) { 129 resource.release(); 130 resource = null; 131 } 132 } 133 134 @Override 135 public boolean isComplete() { 136 return resource != null; 137 } 138 139 @Override 140 public boolean isFailed() { 141 return isError; 142 } 143 144 private void setPlaceHolder() { 145 if (!canSetPlaceholder()) return; 146 147 if (placeholderDrawable == null && placeholderResourceId > 0) { 148 placeholderDrawable = context.getResources().getDrawable(placeholderResourceId); 149 } 150 target.setPlaceholder(placeholderDrawable); 151 } 152 153 private void setErrorPlaceholder() { 154 if (!canSetPlaceholder()) return; 155 156 if (errorDrawable == null && errorResourceId > 0) { 157 errorDrawable = context.getResources().getDrawable(errorResourceId); 158 } 159 if (errorDrawable == null) { 160 setPlaceHolder(); 161 } else { 162 target.setPlaceholder(errorDrawable); 163 } 164 } 165 166 @Override 167 public void onSizeReady(int width, int height) { 168 if (isCancelled) { 169 return; 170 } 171 172 width = Math.round(sizeMultiplier * width); 173 height = Math.round(sizeMultiplier * height); 174 ResourceDecoder<InputStream, Z> cacheDecoder = loadProvider.getCacheDecoder(); 175 ResourceDecoder<T, Z> decoder = loadProvider.getSourceDecoder(); 176 ResourceEncoder <Z> encoder = loadProvider.getEncoder(); 177 ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder(); 178 ModelLoader<A, T> modelLoader = loadProvider.getModelLoader(); 179 180 final String id = modelLoader.getId(model); 181 final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height); 182 183 loadedFromMemoryCache = true; 184 loadStatus = engine.load(id, width, height, cacheDecoder, dataFetcher, decoder, transformation, 185 encoder, transcoder, priority, isMemoryCacheable, this); 186 loadedFromMemoryCache = resource != null; 187 } 188 189 private boolean canSetImage() { 190 return requestCoordinator == null || requestCoordinator.canSetImage(this); 191 } 192 193 private boolean canSetPlaceholder() { 194 return requestCoordinator == null || requestCoordinator.canSetPlaceholder(this); 195 } 196 197 private boolean isAnyImageSet() { 198 return requestCoordinator != null && requestCoordinator.isAnyRequestComplete(); 199 } 200 201 @Override 202 public void onResourceReady(Resource resource) { 203 if (!canSetImage()) { 204 resource.release(); 205 return; 206 } 207 if (resource == null || !transcodeClass.isAssignableFrom(resource.get().getClass())) { 208 if (resource != null) { 209 resource.release(); 210 } 211 onException(new Exception("Expected to receive an object of " + transcodeClass + " but instead got " + 212 (resource != null ? resource.get() : null))); 213 return; 214 } 215 R result = (R) resource.get(); 216 target.onResourceReady(result); 217 if (!loadedFromMemoryCache && !isAnyImageSet()) { 218 if (animation == null && animationId > 0) { 219 animation = AnimationUtils.loadAnimation(context, animationId); 220 } 221 if (animation != null) { 222 target.startAnimation(animation); 223 } 224 } 225 if (requestListener != null) { 226 requestListener.onImageReady(model, target, loadedFromMemoryCache, isAnyImageSet()); 227 } 228 229 this.resource = resource; 230 } 231 232 @Override 233 public void onException(Exception e) { 234// if (Log.isLoggable(TAG, Log.DEBUG)) { 235 Log.d(TAG, "load failed", e); 236// } 237 238 isError = true; 239 setErrorPlaceholder(); 240 241 //TODO: what if this is a thumbnail request? 242 if (requestListener != null) { 243 requestListener.onException(e, model, target); 244 } 245 } 246} 247