一、基本组件:
- ImageLoaderEngine:任务分发器,负责分发 LoadAndDisplayImageTask和ProcessAndDisplayImageTask 给线程池执行
- LoadAndDisplayImageTask:用于加载显示图片的任务
- ProcessAndDisplayImageTask:用于处理并显示图像的任务
- ImageAware:显示图片的对象,可以是ImageView
- DiskCache:
- ImageDecoder:图片解码器,将InputStream转换为Bitmap对象
- MemoryCache:内存缓存
- BitmapProcessor:负责BItmap进行处理
- BitmapDisplayer:将Bitmap显示在对应的ImageAware上
二、ImageLoader.displayImage()分析:
1 public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options, 2 ImageSize targetSize, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) { 3 //检测参数有效性 4 checkConfiguration(); 5 if (imageAware == null) { 6 throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS); 7 } 8 if (listener == null) { 9 listener = defaultListener; 10 } 11 if (options == null) { 12 options = configuration.defaultDisplayImageOptions; 13 } 14 15 if (TextUtils.isEmpty(uri)) { 16 engine.cancelDisplayTaskFor(imageAware); 17 listener.onLoadingStarted(uri, imageAware.getWrappedView()); 18 if (options.shouldShowImageForEmptyUri()) { 19 imageAware.setImageDrawable(options.getImageForEmptyUri(configuration.resources)); 20 } else { 21 imageAware.setImageDrawable(null); 22 } 23 listener.onLoadingComplete(uri, imageAware.getWrappedView(), null); 24 return; 25 } 26 27 if (targetSize == null) { 28 targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, configuration.getMaxImageSize()); 29 } 30 String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize); 31 engine.prepareDisplayTaskFor(imageAware, memoryCacheKey); 32 33 listener.onLoadingStarted(uri, imageAware.getWrappedView()); 34 35 //尝试从内存中获取缓存,使用了MemoryCache组件 36 Bitmap bmp = configuration.memoryCache.get(memoryCacheKey); 37 if (bmp != null && !bmp.isRecycled()) { 38 //若已在内存缓存 39 L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey); 40 //如果需要处理,则调用ProcessAndDisplayImageTask.run()Bitmap进行处理 41 if (options.shouldPostProcess()) { 42 ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey, 43 options, listener, progressListener, engine.getLockForUri(uri)); 44 ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo, 45 defineHandler(options)); 46 if (options.isSyncLoading()) { 47 //处理Bitmap 48 displayTask.run(); 49 } else { 50 engine.submit(displayTask); 51 } 52 } else { 53 //无需处理Bitmap,则调用BitmapDisplayer组件将bitmap显示在imageAware上 54 options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE); 55 //回调加载完成 56 listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp); 57 } 58 } else { 59 //若内存中无该缓存 60 if (options.shouldShowImageOnLoading()) { 61 imageAware.setImageDrawable(options.getImageOnLoading(configuration.resources)); 62 } else if (options.isResetViewBeforeLoading()) { 63 imageAware.setImageDrawable(null); 64 } 65 //封装加载信息 66 ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey, 67 options, listener, progressListener, engine.getLockForUri(uri)); 68 //创建LoadAndDisplayImageTask组件 69 LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo, 70 defineHandler(options)); 71 if (options.isSyncLoading()) { 72 //从磁盘或网络加载,下面会分析 73 displayTask.run(); 74 } else { 75 engine.submit(displayTask); 76 } 77 } 78 } 79 80 81 82 @Override 83 public void run() { 84 if (waitIfPaused()) return; 85 if (delayIfNeed()) return; 86 87 ReentrantLock loadFromUriLock = imageLoadingInfo.loadFromUriLock; 88 L.d(LOG_START_DISPLAY_IMAGE_TASK, memoryCacheKey); 89 if (loadFromUriLock.isLocked()) { 90 L.d(LOG_WAITING_FOR_IMAGE_LOADED, memoryCacheKey); 91 } 92 93 loadFromUriLock.lock(); 94 Bitmap bmp; 95 try { 96 checkTaskNotActual(); 97 //尝试从内存获取 98 bmp = configuration.memoryCache.get(memoryCacheKey); 99 if (bmp == null || bmp.isRecycled()) { 100 //未在内存缓存,下面将分析tryLoadBitmap 101 bmp = tryLoadBitmap(); 102 if (bmp == null) return; // listener callback already was fired 103 104 checkTaskNotActual(); 105 checkTaskInterrupted(); 106 107 if (options.shouldPreProcess()) { 108 L.d(LOG_PREPROCESS_IMAGE, memoryCacheKey); 109 bmp = options.getPreProcessor().process(bmp); 110 if (bmp == null) { 111 L.e(ERROR_PRE_PROCESSOR_NULL, memoryCacheKey); 112 } 113 } 114 115 if (bmp != null && options.isCacheInMemory()) { 116 L.d(LOG_CACHE_IMAGE_IN_MEMORY, memoryCacheKey); 117 configuration.memoryCache.put(memoryCacheKey, bmp); 118 } 119 } else { 120 loadedFrom = LoadedFrom.MEMORY_CACHE; 121 L.d(LOG_GET_IMAGE_FROM_MEMORY_CACHE_AFTER_WAITING, memoryCacheKey); 122 } 123 124 if (bmp != null && options.shouldPostProcess()) { 125 L.d(LOG_POSTPROCESS_IMAGE, memoryCacheKey); 126 bmp = options.getPostProcessor().process(bmp); 127 if (bmp == null) { 128 L.e(ERROR_POST_PROCESSOR_NULL, memoryCacheKey); 129 } 130 } 131 checkTaskNotActual(); 132 checkTaskInterrupted(); 133 } catch (TaskCancelledException e) { 134 fireCancelEvent(); 135 return; 136 } finally { 137 loadFromUriLock.unlock(); 138 } 139 140 DisplayBitmapTask displayBitmapTask = new DisplayBitmapTask(bmp, imageLoadingInfo, engine, loadedFrom); 141 runTask(displayBitmapTask, syncLoading, handler, engine); 142 } 143 144 145 private Bitmap tryLoadBitmap() throws TaskCancelledException { 146 Bitmap bitmap = null; 147 try { 148 //调用DiskCache组件尝试从磁盘获取缓存 149 File imageFile = configuration.diskCache.get(uri); 150 if (imageFile != null && imageFile.exists() && imageFile.length() > 0) { 151 //若已在磁盘缓存 152 L.d(LOG_LOAD_IMAGE_FROM_DISK_CACHE, memoryCacheKey); 153 loadedFrom = LoadedFrom.DISC_CACHE; 154 155 checkTaskNotActual(); 156 //将磁盘文件转换为bitmap对象 157 bitmap = decodeImage(Scheme.FILE.wrap(imageFile.getAbsolutePath())); 158 } 159 if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) { 160 //若不在磁盘缓存 161 L.d(LOG_LOAD_IMAGE_FROM_NETWORK, memoryCacheKey); 162 loadedFrom = LoadedFrom.NETWORK; 163 164 String imageUriForDecoding = uri; 165 //从网络加载,并放入磁盘缓存,下面分析 166 if (options.isCacheOnDisk() && tryCacheImageOnDisk()) { 167 imageFile = configuration.diskCache.get(uri); 168 if (imageFile != null) { 169 imageUriForDecoding = Scheme.FILE.wrap(imageFile.getAbsolutePath()); 170 } 171 } 172 173 checkTaskNotActual(); 174 bitmap = decodeImage(imageUriForDecoding); 175 176 if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) { 177 fireFailEvent(FailType.DECODING_ERROR, null); 178 } 179 } 180 } catch (IllegalStateException e) { 181 fireFailEvent(FailType.NETWORK_DENIED, null); 182 } catch (TaskCancelledException e) { 183 throw e; 184 } catch (IOException e) { 185 L.e(e); 186 fireFailEvent(FailType.IO_ERROR, e); 187 } catch (OutOfMemoryError e) { 188 L.e(e); 189 fireFailEvent(FailType.OUT_OF_MEMORY, e); 190 } catch (Throwable e) { 191 L.e(e); 192 fireFailEvent(FailType.UNKNOWN, e); 193 } 194 return bitmap; 195 } 196 197 198 private boolean tryCacheImageOnDisk() throws TaskCancelledException { 199 L.d(LOG_CACHE_IMAGE_ON_DISK, memoryCacheKey); 200 201 boolean loaded; 202 try { 203 //下载图片,下面分析 204 loaded = downloadImage(); 205 if (loaded) { 206 int width = configuration.maxImageWidthForDiskCache; 207 int height = configuration.maxImageHeightForDiskCache; 208 if (width > 0 || height > 0) { 209 L.d(LOG_RESIZE_CACHED_IMAGE_FILE, memoryCacheKey); 210 resizeAndSaveImage(width, height); // TODO : process boolean result 211 } 212 } 213 } catch (IOException e) { 214 L.e(e); 215 loaded = false; 216 } 217 return loaded; 218 } 219 220 private boolean downloadImage() throws IOException { 221 //获取输入流 222 InputStream is = getDownloader().getStream(uri, options.getExtraForDownloader()); 223 if (is == null) { 224 L.e(ERROR_NO_IMAGE_STREAM, memoryCacheKey); 225 return false; 226 } else { 227 try { 228 //保存到磁盘缓存 229 return configuration.diskCache.save(uri, is, this); 230 } finally { 231 IoUtils.closeSilently(is); 232 } 233 } 234 }
大概流程如下:
- 尝试从内存缓存获取数据
- 若已缓存,处理该Bitmap,交给BitmapDisplayer显示
- 若不在,则从磁盘获取
- 若在磁盘中,则解析文件到Bitmap,缓存到内存缓存,显示
- 若不在磁盘中,交个ImageDownLoader从网络下载,放入磁盘缓存,内存缓存,最后显示
时间: 2024-11-05 22:01:14