码迷,mamicode.com
首页 > 移动开发 > 详细

Android进阶-UIL分析

时间:2016-04-16 13:55:18      阅读:254      评论:0      收藏:0      [点我收藏+]

标签:

一、基本组件:

  1. ImageLoaderEngine:任务分发器,负责分发 LoadAndDisplayImageTask和ProcessAndDisplayImageTask 给线程池执行
  2. LoadAndDisplayImageTask:用于加载显示图片的任务
  3. ProcessAndDisplayImageTask:用于处理并显示图像的任务
  4. ImageAware:显示图片的对象,可以是ImageView
  5. DiskCache:
  6. ImageDecoder:图片解码器,将InputStream转换为Bitmap对象
  7. MemoryCache:内存缓存
  8. BitmapProcessor:负责BItmap进行处理
  9. 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     }

大概流程如下:

  1. 尝试从内存缓存获取数据
    1. 若已缓存,处理该Bitmap,交给BitmapDisplayer显示
    2. 若不在,则从磁盘获取
      1. 若在磁盘中,则解析文件到Bitmap,缓存到内存缓存,显示
      2. 若不在磁盘中,交个ImageDownLoader从网络下载,放入磁盘缓存,内存缓存,最后显示

技术分享

Android进阶-UIL分析

标签:

原文地址:http://www.cnblogs.com/gatsbydhn/p/5398104.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!