/* * Copyright (C) 2013 Peng fei Pan <sky@xiaopan.me> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package me.xiaopan.sketch.request; import android.graphics.Bitmap; import android.widget.ImageView.ScaleType; import me.xiaopan.sketch.Configuration; import me.xiaopan.sketch.SLogType; import me.xiaopan.sketch.Sketch; import me.xiaopan.sketch.SLog; import me.xiaopan.sketch.process.ImageProcessor; import me.xiaopan.sketch.util.SketchUtils; /** * 加载Helper,负责组织、收集、初始化加载参数,最后执行commit()提交请求 */ public class LoadHelper { protected String logName = "LoadHelper"; protected Sketch sketch; protected boolean sync; protected LoadInfo loadInfo = new LoadInfo(); protected LoadOptions loadOptions = new LoadOptions(); protected LoadListener loadListener; protected DownloadProgressListener downloadProgressListener; public LoadHelper(Sketch sketch, String uri) { this.sketch = sketch; this.loadInfo.reset(uri); } /** * 禁用磁盘缓存 */ @SuppressWarnings("unused") public LoadHelper disableCacheInDisk() { loadOptions.setCacheInDiskDisabled(true); return this; } /** * 禁用BitmapPool */ @SuppressWarnings("unused") public LoadHelper disableBitmapPool() { loadOptions.setBitmapPoolDisabled(true); return this; } /** * 设置请求Level */ @SuppressWarnings("unused") public LoadHelper requestLevel(RequestLevel requestLevel) { if (requestLevel != null) { loadOptions.setRequestLevel(requestLevel); loadOptions.setRequestLevelFrom(null); } return this; } /** * 解码Gif图片 */ @SuppressWarnings("unused") public LoadHelper decodeGifImage() { loadOptions.setDecodeGifImage(true); return this; } /** * 设置最大尺寸,在解码的时候会使用此Size来计算inSimpleSize */ @SuppressWarnings("unused") public LoadHelper maxSize(int width, int height) { loadOptions.setMaxSize(width, height); return this; } /** * 裁剪图片,将原始图片加载到内存中之后根据resize进行裁剪。裁剪的原则就是最终返回的图片的比例一定是跟resize一样的, * 但尺寸不一定会等于resi,也有可能小于resize,如果需要必须同resize一致可以设置forceUseResize */ public LoadHelper resize(int width, int height) { loadOptions.setResize(width, height); return this; } /** * 裁剪图片,将原始图片加载到内存中之后根据resize进行裁剪。裁剪的原则就是最终返回的图片的比例一定是跟resize一样的, * 但尺寸不一定会等于resize,也有可能小于resize,如果需要必须同resize一致可以设置forceUseResize */ public LoadHelper resize(int width, int height, ScaleType scaleType) { loadOptions.setResize(new Resize(width, height, scaleType)); return this; } /** * 强制使经过resize处理后的图片同resize的尺寸一致 */ public LoadHelper forceUseResize() { loadOptions.setForceUseResize(true); return this; } /** * 返回低质量的图片 */ public LoadHelper lowQualityImage() { loadOptions.setLowQualityImage(true); return this; } /** * 设置图片处理器,图片处理器会根据resize创建一张新的图片 */ @SuppressWarnings("unused") public LoadHelper processor(ImageProcessor processor) { loadOptions.setImageProcessor(processor); return this; } /** * 设置图片质量 */ @SuppressWarnings("unused") public LoadHelper bitmapConfig(Bitmap.Config config) { loadOptions.setBitmapConfig(config); return this; } /** * 设置优先考虑质量还是速度 */ @SuppressWarnings("unused") public LoadHelper inPreferQualityOverSpeed(boolean inPreferQualityOverSpeed) { loadOptions.setInPreferQualityOverSpeed(inPreferQualityOverSpeed); return this; } /** * 开启缩略图模式 */ @SuppressWarnings("unused") public LoadHelper thumbnailMode() { loadOptions.setThumbnailMode(true); return this; } /** * 为了加快速度,将经过ImageProcessor、resize或thumbnailMode处理过的图片保存到磁盘缓存中,下次就直接读取 */ @SuppressWarnings("unused") public LoadHelper cacheProcessedImageInDisk() { loadOptions.setCacheProcessedImageInDisk(true); return this; } /** * 纠正图片的方向,让被旋转了的图片以正常方向显示 */ @SuppressWarnings("unused") public LoadHelper correctImageOrientation() { loadOptions.setCorrectImageOrientation(true); return this; } /** * 批量设置加载参数,这会是一个合并的过程,并不会完全覆盖 */ public LoadHelper options(LoadOptions newOptions) { loadOptions.merge(newOptions); return this; } /** * 批量设置加载参数,你只需要提前将LoadOptions通过Sketch.putLoadOptions()方法存起来, * 然后在这里指定其名称即可,另外这会是一个合并的过程,并不会完全覆盖 */ @SuppressWarnings("unused") public LoadHelper optionsByName(Enum<?> optionsName) { return options(Sketch.getLoadOptions(optionsName)); } /** * 设置加载监听器 */ public LoadHelper listener(LoadListener loadListener) { this.loadListener = loadListener; return this; } /** * 设置下载进度监听器 */ @SuppressWarnings("unused") public LoadHelper downloadProgressListener(DownloadProgressListener downloadProgressListener) { this.downloadProgressListener = downloadProgressListener; return this; } /** * 同步处理 */ @SuppressWarnings("unused") public LoadHelper sync() { this.sync = true; return this; } /** * 提交 */ public LoadRequest commit() { if (sync && SketchUtils.isMainThread()) { throw new IllegalStateException("Cannot sync perform the load in the UI thread "); } CallbackHandler.postCallbackStarted(loadListener, sync); preProcess(); if (!checkUri()) { return null; } if (!checkRequestLevel()) { return null; } return submitRequest(); } /** * 对属性进行预处理 */ protected void preProcess() { Configuration configuration = sketch.getConfiguration(); // 检查Resize的宽高都必须大于0 Resize resize = loadOptions.getResize(); if (resize != null && (resize.getWidth() == 0 || resize.getHeight() == 0)) { throw new IllegalArgumentException("Resize width and height must be > 0"); } // 没有设置maxSize的话,就用默认的maxSize if (loadOptions.getMaxSize() == null) { loadOptions.setMaxSize(configuration.getImageSizeCalculator().getDefaultImageMaxSize(configuration.getContext())); } // 检查MaxSize的宽或高大于0即可 MaxSize maxSize = loadOptions.getMaxSize(); if (maxSize != null && maxSize.getWidth() <= 0 && maxSize.getHeight() <= 0) { throw new IllegalArgumentException("MaxSize width or height must be > 0"); } // 没有ImageProcessor但有resize的话就需要设置一个默认的图片裁剪处理器 if (loadOptions.getImageProcessor() == null && resize != null) { loadOptions.setImageProcessor(configuration.getResizeImageProcessor()); } // 如果设置了全局使用低质量图片的话就强制使用低质量的图片 if (configuration.isGlobalLowQualityImage()) { loadOptions.setLowQualityImage(true); } // 如果设置了全局解码质量优先 if (sketch.getConfiguration().isGlobalInPreferQualityOverSpeed()) { loadOptions.setInPreferQualityOverSpeed(true); } // 如果没有设置请求Level的话就跟据暂停下载和暂停加载功能来设置请求Level if (loadOptions.getRequestLevel() == null) { if (configuration.isGlobalPauseDownload()) { loadOptions.setRequestLevel(RequestLevel.LOCAL); loadOptions.setRequestLevelFrom(RequestLevelFrom.PAUSE_DOWNLOAD); } // 暂停加载对于加载请求并不起作用,因此这里不予处理 } // 根据URI和加载选项生成请求ID if (loadInfo.getKey() == null) { loadInfo.setKey(SketchUtils.makeRequestKey(loadInfo.getUri(), loadOptions)); } } private boolean checkUri() { if (loadInfo.getUri() == null || "".equals(loadInfo.getUri().trim())) { if (SLogType.REQUEST.isEnabled()) { SLog.e(SLogType.REQUEST, logName, "uri is null or empty"); } CallbackHandler.postCallbackError(loadListener, ErrorCause.URI_NULL_OR_EMPTY, sync); return false; } if (loadInfo.getUriScheme() == null) { SLog.e(SLogType.REQUEST, logName, "unknown uri scheme. %s", loadInfo.getUri()); CallbackHandler.postCallbackError(loadListener, ErrorCause.URI_NO_SUPPORT, sync); return false; } return true; } private boolean checkRequestLevel() { // 如果只从本地加载并且是网络请求并且磁盘中没有缓存就结束吧 if (loadOptions.getRequestLevel() == RequestLevel.LOCAL && loadInfo.getUriScheme() == UriScheme.NET && !sketch.getConfiguration().getDiskCache().exist(loadInfo.getDiskCacheKey())) { boolean isPauseDownload = loadOptions.getRequestLevelFrom() == RequestLevelFrom.PAUSE_DOWNLOAD; if (SLogType.REQUEST.isEnabled()) { SLog.w(SLogType.REQUEST, logName, "canceled. %s. %s", isPauseDownload ? "pause download" : "requestLevel is local", loadInfo.getKey()); } CancelCause cancelCause = isPauseDownload ? CancelCause.PAUSE_DOWNLOAD : CancelCause.REQUEST_LEVEL_IS_LOCAL; CallbackHandler.postCallbackCanceled(loadListener, cancelCause, sync); return false; } return true; } private LoadRequest submitRequest() { RequestFactory requestFactory = sketch.getConfiguration().getRequestFactory(); LoadRequest request = requestFactory.newLoadRequest(sketch, loadInfo, loadOptions, loadListener, downloadProgressListener); request.setSync(sync); request.submit(); return request; } }