/*
* 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;
import android.app.Application;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import java.util.HashMap;
import java.util.Map;
import me.xiaopan.sketch.feature.ImagePreprocessor;
import me.xiaopan.sketch.request.CancelCause;
import me.xiaopan.sketch.request.DisplayHelper;
import me.xiaopan.sketch.request.DisplayOptions;
import me.xiaopan.sketch.request.DisplayParams;
import me.xiaopan.sketch.request.DisplayRequest;
import me.xiaopan.sketch.request.DownloadHelper;
import me.xiaopan.sketch.request.DownloadListener;
import me.xiaopan.sketch.request.DownloadOptions;
import me.xiaopan.sketch.request.ImageViewInterface;
import me.xiaopan.sketch.request.LoadHelper;
import me.xiaopan.sketch.request.LoadListener;
import me.xiaopan.sketch.request.LoadOptions;
import me.xiaopan.sketch.request.UriScheme;
import me.xiaopan.sketch.util.SketchUtils;
/**
* Sketch是一个功能强大且全面的图片加载器,可以从网络或者本地加载图片,支持gif、手势缩放以及分块显示超大图
* <ul>
* <li>display():显示图片到ImageView上</li>
* <li>load():加载图片到内存中</li>
* <li>download():下载图片到磁盘上</li>
* </ul>
*/
public class Sketch {
public static final String TAG = "Sketch";
private static Sketch instance;
private static Map<Enum<?>, Object> optionsMap;
private Configuration configuration;
private Sketch(Context context) {
SLog.i(String.format("Version %s %s(%d)", BuildConfig.BUILD_TYPE, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE));
this.configuration = new Configuration(context);
}
/**
* 获取Sketch实例
*
* @param context 用于初始化Sketch
* @return Sketch
*/
public static Sketch with(Context context) {
if (instance == null) {
synchronized (Sketch.class) {
if (instance == null) {
instance = new Sketch(context);
}
}
}
return instance;
}
/**
* 获取配置
*
* @return Configuration
*/
public Configuration getConfiguration() {
return configuration;
}
/**
* 下载图片
*
* @param uri 图片Uri,支持以下几种
* <ul>
* <li>http://site.com/image.png // from Web</li>
* <li>https://site.com/image.png // from Web</li>
* </ul>
* @param listener 监听下载过程
* @return DownloadHelper 你可以继续通过DownloadHelper设置一下参数,最后调用其commit()方法提交即可
*/
@SuppressWarnings("unused")
public DownloadHelper download(String uri, DownloadListener listener) {
return configuration.getHelperFactory().getDownloadHelper(this, uri).listener(listener);
}
/**
* 根据URI加载图片
*
* @param uri 图片Uri,支持以下几种
* <ul>
* <li>http://site.com/image.png // from Web</li>
* <li>https://site.com/image.png // from Web</li>
* <li>file:///mnt/sdcard/image.png // from SD card</li>
* <li>/mnt/sdcard/image.png // from SD card</li>
* <li>/mnt/sdcard/app.apk // from SD card apk file</li>
* <li>content://media/external/audio/albumart/13 // from content provider</li>
* <li>asset://image.png // from assets</li>
* <li>"drawable://" + R.drawable.image // from drawables (only images, non-9patch)</li>
* </ul>
* @param listener 监听下载过程
* @return LoadHelper 你可以继续通过LoadHelper设置一下参数,最后调用其commit()方法提交即可
*/
public LoadHelper load(String uri, LoadListener listener) {
return configuration.getHelperFactory().getLoadHelper(this, uri).listener(listener);
}
/**
* 加载Asset中的图片
*
* @param fileName asset中图片文件的名称
* @param listener 监听加载过程
* @return LoadHelper 你可以继续通过LoadHelper设置一下参数,最后调用其commit()方法提交即可
*/
@SuppressWarnings("unused")
public LoadHelper loadFromAsset(String fileName, LoadListener listener) {
String uri = UriScheme.ASSET.createUri(fileName);
return configuration.getHelperFactory().getLoadHelper(this, uri).listener(listener);
}
/**
* 加载资源中的图片
*
* @param drawableResId 图片资源的ID
* @param listener 监听加载过程
* @return LoadHelper 你可以继续通过LoadHelper设置一下参数,最后调用其commit()方法提交即可
*/
@SuppressWarnings("unused")
public LoadHelper loadFromResource(int drawableResId, LoadListener listener) {
String uri = UriScheme.DRAWABLE.createUri(String.valueOf(drawableResId));
return configuration.getHelperFactory().getLoadHelper(this, uri).listener(listener);
}
/**
* 加载URI指向的图片
*
* @param uri 图片Uri,会通过ContentResolver().openInputStream(Uri)方法来读取图片
* @param listener 监听加载过程
* @return LoadHelper 你可以继续通过LoadHelper设置一下参数,最后调用其commit()方法提交即可
*/
@SuppressWarnings("unused")
public LoadHelper loadFromURI(Uri uri, LoadListener listener) {
return configuration.getHelperFactory().getLoadHelper(this, uri.toString()).listener(listener);
}
/**
* 加载已安装APP的图标
*
* @param packageName 已安装APP的包名
* @param versionCode 已安装APP的版本号
* @param listener 监听加载过程
* @return LoadHelper 你可以继续通过LoadHelper设置一下参数,最后调用其commit()方法提交即可
*/
@SuppressWarnings("unused")
public LoadHelper loadInstalledAppIcon(String packageName, int versionCode, LoadListener listener) {
String uri = ImagePreprocessor.createInstalledAppIconUri(packageName, versionCode);
return configuration.getHelperFactory().getLoadHelper(this, uri).listener(listener);
}
/**
* 显示图片
*
* @param uri 图片Uri,支持以下几种
* <ul>
* <li>http://site.com/image.png // from Web</li>
* <li>https://site.com/image.png // from Web</li>
* <li>file:///mnt/sdcard/image.png // from SD card</li>
* <li>/mnt/sdcard/image.png // from SD card</li>
* <li>/mnt/sdcard/app.apk // from SD card apk file</li>
* <li>content://media/external/audio/albumart/13 // from content provider</li>
* <li>asset://image.png // from assets</li>
* <li>"drawable://" + R.drawable.image // from drawables (only images, non-9patch)</li>
* </ul>
* @param imageViewInterface 默认实现是SketchImageView
* @return DisplayHelper 你可以继续通过DisplayHelper设置一下参数,最后调用其commit()方法提交即可
*/
public DisplayHelper display(String uri, ImageViewInterface imageViewInterface) {
return configuration.getHelperFactory().getDisplayHelper(this, uri, imageViewInterface);
}
/**
* 显示Asset中的图片
*
* @param fileName asset中图片文件的名称
* @param imageViewInterface 默认实现是SketchImageView
* @return DisplayHelper 你可以继续通过DisplayHelper设置一下参数,最后调用其commit()方法提交即可
*/
public DisplayHelper displayFromAsset(String fileName, ImageViewInterface imageViewInterface) {
return configuration.getHelperFactory().getDisplayHelper(this, UriScheme.ASSET.createUri(fileName), imageViewInterface);
}
/**
* 显示资源中的图片
*
* @param drawableResId 图片资源的ID
* @param imageViewInterface 默认实现是SketchImageView
* @return DisplayHelper 你可以继续通过DisplayHelper设置一下参数,最后调用其commit()方法提交即可
*/
public DisplayHelper displayFromResource(int drawableResId, ImageViewInterface imageViewInterface) {
return configuration.getHelperFactory().getDisplayHelper(this, UriScheme.DRAWABLE.createUri(String.valueOf(drawableResId)), imageViewInterface);
}
/**
* 显示URI指向的图片
*
* @param uri 图片Uri,会通过ContentResolver().openInputStream(Uri)方法来读取图片
* @param imageViewInterface 默认实现是SketchImageView
* @return DisplayHelper 你可以继续通过DisplayHelper设置一下参数,最后调用其commit()方法提交即可
*/
public DisplayHelper displayFromURI(Uri uri, ImageViewInterface imageViewInterface) {
return configuration.getHelperFactory().getDisplayHelper(this, uri != null ? uri.toString() : null, imageViewInterface);
}
/**
* 显示已安装APP的图标
*
* @param packageName 已安装APP的包名
* @param versionCode 已安装APP的版本号
* @param imageViewInterface 默认实现是SketchImageView
* @return DisplayHelper 你可以继续通过DisplayHelper设置一下参数,最后调用其commit()方法提交即可
*/
public DisplayHelper displayInstalledAppIcon(String packageName, int versionCode, ImageViewInterface imageViewInterface) {
return configuration.getHelperFactory().getDisplayHelper(this, ImagePreprocessor.createInstalledAppIconUri(packageName, versionCode), imageViewInterface);
}
/**
* 显示图片,主要用于配合SketchImageView兼容RecyclerView以及点击重试功能
*
* @param displayParams 显示参数缓存
* @param imageViewInterface 默认实现是SketchImageView
* @return DisplayHelper 你可以继续通过DisplayHelper设置一下参数,最后调用其commit()方法提交即可
*/
public DisplayHelper display(DisplayParams displayParams, ImageViewInterface imageViewInterface) {
return configuration.getHelperFactory().getDisplayHelper(this, displayParams, imageViewInterface);
}
/**
* 修整内存缓存,4.0以下你需要重写Application的onTrimMemory(int)方法,然后调用这个方法
*
* @param level 修剪级别,对应APP的不同状态,对应ComponentCallbacks2里的常量
* @see android.content.ComponentCallbacks2
*/
public void onTrimMemory(int level) {
// ICE_CREAM_SANDWICH以上版本已经自动注册了onTrimMemory监听,因此无需再在你的Application的onTrimMemory方法中调用此方法
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
StackTraceElement[] stackTraceElements = new Exception().getStackTrace();
if (!SketchUtils.invokeIn(stackTraceElements, Application.class, "onTrimMemory")) {
return;
}
}
if (SLogType.BASE.isEnabled()) {
SLog.w(SLogType.BASE, "Trim of memory, level= %s", SketchUtils.getTrimLevelName(level));
}
configuration.getMemoryCache().trimMemory(level);
configuration.getBitmapPool().trimMemory(level);
}
/**
* 当内存低时直接清空全部内存缓存,4.0以下你需要重写Application的onLowMemory方法,然后调用这个方法
*/
public void onLowMemory() {
// ICE_CREAM_SANDWICH以上版本已经自动注册了onLowMemory监听,因此无需再在你的Application的onLowMemory方法中调用此方法
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
StackTraceElement[] stackTraceElements = new Exception().getStackTrace();
if (!SketchUtils.invokeIn(stackTraceElements, Application.class, "onLowMemory")) {
return;
}
}
if (SLogType.BASE.isEnabled()) {
SLog.w(SLogType.BASE, "Memory is very low, clean memory cache and bitmap pool");
}
configuration.getMemoryCache().clear();
configuration.getBitmapPool().clear();
}
/**
* 取消请求
*
* @param imageViewInterface 会通过ImageViewInterface的Drawable找到正在执行的请求,然后取消它
* @return true:当前ImageView有正在执行的任务并且取消成功;false:当前ImageView没有正在执行的任务
*/
public static boolean cancel(ImageViewInterface imageViewInterface) {
final DisplayRequest displayRequest = SketchUtils.findDisplayRequest(imageViewInterface);
if (displayRequest != null && !displayRequest.isFinished()) {
displayRequest.cancel(CancelCause.BE_CANCELLED);
return true;
} else {
return false;
}
}
/**
* 安装选项Map
*/
private static void installOptionsMap() {
if (optionsMap == null) {
synchronized (Sketch.class) {
if (optionsMap == null) {
optionsMap = new HashMap<Enum<?>, Object>();
}
}
}
}
/**
* 存入一个下载选项
*
* @param optionsName 选项名称
* @param options 下载选项
*/
@SuppressWarnings("unused")
public static void putOptions(Enum<?> optionsName, DownloadOptions options) {
installOptionsMap();
optionsMap.put(optionsName, options);
}
/**
* 存入一个加载选项
*
* @param optionsName 选项名称
* @param options 加载选项
*/
@SuppressWarnings("unused")
public static void putOptions(Enum<?> optionsName, LoadOptions options) {
installOptionsMap();
optionsMap.put(optionsName, options);
}
/**
* 存入一个显示选项
*
* @param optionsName 选项名称
* @param options 显示选项
*/
public static void putOptions(Enum<?> optionsName, DisplayOptions options) {
installOptionsMap();
optionsMap.put(optionsName, options);
}
/**
* 获取之前存入的下载选项
*
* @param optionsName 选项名称
*/
public static DownloadOptions getDownloadOptions(Enum<?> optionsName) {
return optionsMap != null ? (DownloadOptions) optionsMap.get(optionsName) : null;
}
/**
* 获取之前存入的加载选项
*
* @param optionsName 选项名称
*/
public static LoadOptions getLoadOptions(Enum<?> optionsName) {
return optionsMap != null ? (LoadOptions) optionsMap.get(optionsName) : null;
}
/**
* 获取之前存入的显示选项
*
* @param optionsName 选项名称
*/
public static DisplayOptions getDisplayOptions(Enum<?> optionsName) {
return optionsMap != null ? (DisplayOptions) optionsMap.get(optionsName) : null;
}
}