1 package com.bumptech.glide.load.model; 2 3 import android.os.ParcelFileDescriptor; 4 import android.util.Log; 5 6 import com.bumptech.glide.Priority; 7 import com.bumptech.glide.load.data.DataFetcher; 8 9 import java.io.InputStream; 10 11 /** 12 * A wrapper model loader that provides both an {@link java.io.InputStream} and a 13 * {@link android.os.ParcelFileDescriptor} for a given model type by wrapping an 14 * {@link com.bumptech.glide.load.model.ModelLoader} for {@link java.io.InputStream}s for the given model type and an 15 * {@link com.bumptech.glide.load.model.ModelLoader} for {@link android.os.ParcelFileDescriptor} for the given model 16 * type. 17 * 18 * @param <A> The model type. 19 */ 20 public class ImageVideoModelLoader<A> implements ModelLoader<A, ImageVideoWrapper> { 21 private static final String TAG = "IVML"; 22 23 private final ModelLoader<A, InputStream> streamLoader; 24 private final ModelLoader<A, ParcelFileDescriptor> fileDescriptorLoader; 25 26 public ImageVideoModelLoader(ModelLoader<A, InputStream> streamLoader, 27 ModelLoader<A, ParcelFileDescriptor> fileDescriptorLoader) { 28 if (streamLoader == null && fileDescriptorLoader == null) { 29 throw new NullPointerException("At least one of streamLoader and fileDescriptorLoader must be non null"); 30 } 31 this.streamLoader = streamLoader; 32 this.fileDescriptorLoader = fileDescriptorLoader; 33 } 34 35 @Override 36 public DataFetcher<ImageVideoWrapper> getResourceFetcher(A model, int width, int height) { 37 DataFetcher<InputStream> streamFetcher = null; 38 if (streamLoader != null) { 39 streamFetcher = streamLoader.getResourceFetcher(model, width, height); 40 } 41 DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher = null; 42 if (fileDescriptorLoader != null) { 43 fileDescriptorFetcher = fileDescriptorLoader.getResourceFetcher(model, width, height); 44 } 45 46 if (streamFetcher != null || fileDescriptorFetcher != null) { 47 return new ImageVideoFetcher(streamFetcher, fileDescriptorFetcher); 48 } else { 49 return null; 50 } 51 } 52 53 static class ImageVideoFetcher implements DataFetcher<ImageVideoWrapper> { 54 private final DataFetcher<InputStream> streamFetcher; 55 private final DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher; 56 57 public ImageVideoFetcher(DataFetcher<InputStream> streamFetcher, 58 DataFetcher<ParcelFileDescriptor> fileDescriptorFetcher) { 59 this.streamFetcher = streamFetcher; 60 this.fileDescriptorFetcher = fileDescriptorFetcher; 61 } 62 63 @SuppressWarnings("resource") 64 // @see ModelLoader.loadData 65 @Override 66 public ImageVideoWrapper loadData(Priority priority) throws Exception { 67 InputStream is = null; 68 if (streamFetcher != null) { 69 try { 70 is = streamFetcher.loadData(priority); 71 } catch (Exception e) { 72 if (Log.isLoggable(TAG, Log.VERBOSE)) { 73 Log.v(TAG, "Exception fetching input stream, trying ParcelFileDescriptor", e); 74 } 75 if (fileDescriptorFetcher == null) { 76 throw e; 77 } 78 } 79 } 80 ParcelFileDescriptor fileDescriptor = null; 81 if (fileDescriptorFetcher != null) { 82 try { 83 fileDescriptor = fileDescriptorFetcher.loadData(priority); 84 } catch (Exception e) { 85 if (Log.isLoggable(TAG, Log.VERBOSE)) { 86 Log.v(TAG, "Exception fetching ParcelFileDescriptor", e); 87 } 88 if (is == null) { 89 throw e; 90 } 91 } 92 } 93 return new ImageVideoWrapper(is, fileDescriptor); 94 } 95 96 @Override 97 public void cleanup() { 98 //TODO: what if this throws? 99 if (streamFetcher != null) { 100 streamFetcher.cleanup(); 101 } 102 if (fileDescriptorFetcher != null) { 103 fileDescriptorFetcher.cleanup(); 104 } 105 } 106 107 @Override 108 public String getId() { 109 // Both the stream fetcher and the file descriptor fetcher should return the same id. 110 if (streamFetcher != null) { 111 return streamFetcher.getId(); 112 } else { 113 return fileDescriptorFetcher.getId(); 114 } 115 } 116 117 @Override 118 public void cancel() { 119 if (streamFetcher != null) { 120 streamFetcher.cancel(); 121 } 122 if (fileDescriptorFetcher != null) { 123 fileDescriptorFetcher.cancel(); 124 } 125 } 126 } 127 } 128