android imageloaderr 怎么设置自定义显示动漫

6464人阅读
Android应用开发(178)
前言& &在中我们对SimpleImageLoader框架进行了基本的介绍,今天我们就从源码的角度来剖析ImageLoader的设计与实现。 && 在我们使用ImageLoader前都会通过一个配置类来设置一些基本的东西,比如加载中的图片、加载失败的图片、缓存策略等等,SimpleImageLoader的设计也是如此。配置类这个比较简单,我们直接看源码吧。ImageLoaderConfig配置/**
* ImageLoader配置类,
* @author mrsimple
public class ImageLoaderConfig {
* 图片缓存配置对象
public BitmapCache bitmapCache = new MemoryCache();
* 加载图片时的loading和加载失败的图片配置对象
public DisplayConfig displayConfig = new DisplayConfig();
* 加载策略
public LoadPolicy loadPolicy = new SerialPolicy();
public int threadCount = Runtime.getRuntime().availableProcessors() + 1;
* @param count
public ImageLoaderConfig setThreadCount(int count) {
threadCount = Math.max(1, count);
public ImageLoaderConfig setCache(BitmapCache cache) {
bitmapCache =
public ImageLoaderConfig setLoadingPlaceholder(int resId) {
displayConfig.loadingResId = resId;
public ImageLoaderConfig setNotFoundPlaceholder(int resId) {
displayConfig.failedResId = resId;
public ImageLoaderConfig setLoadPolicy(LoadPolicy policy) {
if (policy != null) {
loadPolicy =
}& &都是很简单的setter函数,但是不太一样的是这些setter都是返回一个ImageLoaderConfig对象的,在这里也就是返回了自身。这个设计是类似Builder模式的,便于用户的链式调用,例如: private void initImageLoader() {
ImageLoaderConfig config = new ImageLoaderConfig()
.setLoadingPlaceholder(R.drawable.loading)
.setNotFoundPlaceholder(R.drawable.not_found)
.setCache(new DoubleCache(this))
.setThreadCount(4)
.setLoadPolicy(new ReversePolicy());
SimpleImageLoader.getInstance().init(config);
}&&&对于Builder模式不太了解的同学可以参考&。构建好配置对象之后我们就可以通过这个配置对象来初始化SimpleImageLoader了。SimpleImageLoader会根据配置对象来初始化一些内部策略,例如缓存策略、线程数量等。调用init方法后整个ImageLoader就正式启动了。SimpleImageLoader的实现 SimpleImageLoader这个类的职责只是作为用户入口,它的工作其实并没有那么多,只是一个门童罢了。我们看看它的源码吧。/**
* 图片加载类,支持url和本地图片的uri形式加载.根据图片路径格式来判断是网络图片还是本地图片,如果是网络图片则交给SimpleNet框架来加载,
* 如果是本地图片那么则交给mExecutorService从sd卡中加载
* .加载之后直接更新UI,无需用户干预.如果用户设置了缓存策略,那么会将加载到的图片缓存起来.用户也可以设置加载策略,例如顺序加载{@see
* SerialPolicy}和逆向加载{@see ReversePolicy}.
* @author mrsimple
public final class SimpleImageLoader {
/** SimpleImageLoader实例 */
private static SimpleImageLoader sI
/** 网络请求队列
private RequestQueue mImageQ
/** 缓存 */
private volatile BitmapCache mCache = new MemoryCache();
/** 图片加载配置对象 */
private ImageLoaderConfig mC
private SimpleImageLoader() {
* 获取ImageLoader单例
public static SimpleImageLoader getInstance() {
if (sInstance == null) {
synchronized (SimpleImageLoader.class) {
if (sInstance == null) {
sInstance = new SimpleImageLoader();
* 初始化ImageLoader,启动请求队列
* @param config 配置对象
public void init(ImageLoaderConfig config) {
mCache = mConfig.bitmapC
checkConfig();
mImageQueue = new RequestQueue(mConfig.threadCount);
mImageQueue.start();
private void checkConfig() {
if (mConfig == null) {
throw new RuntimeException(
&The config of SimpleImageLoader is Null, please call the init(ImageLoaderConfig config) method to initialize&);
if (mConfig.loadPolicy == null) {
mConfig.loadPolicy = new SerialPolicy();
if (mCache == null) {
mCache = new NoCache();
public void displayImage(ImageView imageView, String uri) {
displayImage(imageView, uri, null, null);
public void displayImage(final ImageView imageView, final String uri,
final DisplayConfig config, final ImageListener listener) {
BitmapRequest request = new BitmapRequest(imageView, uri, config, listener);
// 加载的配置对象,如果没有设置则使用ImageLoader的配置
request.displayConfig = request.displayConfig != null ? request.displayConfig
: mConfig.displayC
// 添加对队列中
mImageQueue.addRequest(request);
// 代码省略...
* 图片加载Listener
* @author mrsimple
public static interface ImageListener {
public void onComplete(ImageView imageView, Bitmap bitmap, String uri);
&从上述代码中我们可以看到SimpleImageLoader的工作比较少,也比较简单。它就是根据用户传递进来的配置来初始化ImageLoader,并且作为图片加载入口,用户调用displayImage之后它会将这个调用封装成一个BitmapRequest请求,然后将该请求添加到请求队列中。BitmapRequest图片加载请求 BitmapRequest只是一个存储了ImageView、图片uri、DisplayConfig以及ImageListener的一个对象,封装这个对象的目的在加载图片时减少参数的个数,***在BitmapRequest的构造函数中我们会将图片uri设置为ImageView的tag,这样做的目的是防止图片错位显示。***BitmapRequest类实现了Compare接口,请求队列会根据它的序列号进行排序,排序策略用户也可以通过配置类来设置,具体细节在加载策略的章节我们再聊吧。&& public BitmapRequest(ImageView imageView, String uri, DisplayConfig config,
ImageListener listener) {
mImageViewRef = new WeakReference&ImageView&(imageView);
displayConfig =
imageListener =
imageUri =
// 设置ImageView的tag为图片的uri
imageView.setTag(uri);
imageUriMd5 = Md5Helper.toMD5(imageUri);
}RequestQueue图片请求队列&&请求队列我们采用了SImpleNet中一样的模式,通过封装一个优先级队列来维持图片加载队列,mSerialNumGenerator会给每一个请求分配一个序列号,PriorityBlockingQueue会根据BitmapRequest的compare策略来决定BitmapRequest的顺序。RequestQueue内部会启动用户指定数量的线程来从请求队列中读取请求,分发线程不断地从队列中读取请求,然后进行图片加载处理,这样ImageLoader就happy起来了。/**
* 请求队列, 使用优先队列,使得请求可以按照优先级进行处理. [ Thread Safe ]
* @author mrsimple
public final class RequestQueue {
* 请求队列 [ Thread-safe ]
private BlockingQueue&BitmapRequest& mRequestQueue = new PriorityBlockingQueue&BitmapRequest&();
* 请求的序列化生成器
private AtomicInteger mSerialNumGenerator = new AtomicInteger(0);
* 默认的核心数
public static int DEFAULT_CORE_NUMS = Runtime.getRuntime().availableProcessors() + 1;
* CPU核心数 + 1个分发线程数
private int mDispatcherNums = DEFAULT_CORE_NUMS;
* NetworkExecutor,执行网络请求的线程
private RequestDispatcher[] mDispatchers =
protected RequestQueue() {
this(DEFAULT_CORE_NUMS);
* @param coreNums 线程核心数
* @param httpStack http执行器
protected RequestQueue(int coreNums) {
mDispatcherNums = coreN
* 启动RequestDispatcher
private final void startDispatchers() {
mDispatchers = new RequestDispatcher[mDispatcherNums];
for (int i = 0; i & mDispatcherN i++) {
mDispatchers[i] = new RequestDispatcher(mRequestQueue);
mDispatchers[i].start();
public void start() {
startDispatchers();
* 停止RequestDispatcher
public void stop() {
if (mDispatchers != null && mDispatchers.length & 0) {
for (int i = 0; i & mDispatchers. i++) {
mDispatchers[i].interrupt();
* 不能重复添加请求
* @param request
public void addRequest(BitmapRequest request) {
if (!mRequestQueue.contains(request)) {
request.serialNum = this.generateSerialNumber();
mRequestQueue.add(request);
Log.d(&&, &### 请求队列中已经含有&);
private int generateSerialNumber() {
return mSerialNumGenerator.incrementAndGet();
RequestDispatcher请求分发& &请求Dispatcher,继承自Thread,从网络请求队列中循环读取请求并且执行,也比较简单,直接上源码吧。final class RequestDispatcher extends Thread {
* 网络请求队列
private BlockingQueue&BitmapRequest& mRequestQ
* @param queue 图片加载请求队列
public RequestDispatcher(BlockingQueue&BitmapRequest& queue) {
mRequestQueue =
public void run() {
while (!this.isInterrupted()) {
final BitmapRequest request = mRequestQueue.take();
if (request.isCancel) {
// 解析图片schema
final String schema = parseSchema(request.imageUri);
// 根据schema获取对应的Loader
Loader imageLoader = LoaderManager.getInstance().getLoader(schema);
// 加载图片
imageLoader.loadImage(request);
} catch (InterruptedException e) {
Log.i(&&, &### 请求分发器退出&);
* 这里是解析图片uri的格式,uri格式为: schema:// + 图片路径。
private String parseSchema(String uri) {
if (uri.contains(&://&)) {
return uri.split(&://&)[0];
Log.e(getName(), &### wrong scheme, image uri is : & + uri);
return &&;
} 第一个重点就是run函数了,不断地从队列中获取请求,然后解析到图片uri的schema,从schema的格式就可以知道它是存储在哪里的图片。例如网络图片对象的schema是http或者https,sd卡存储的图片对应的schema为file。根据schema我们从LoaderManager中获取对应的Loader来加载图片,这个设计保证了SimpleImageLoader可加载图片类型的可扩展性,这就是为什么会增加loader这个包的原因。用户只需要根据uri的格式来构造图片uri,并且实现自己的Loader类,然后将Loader对象注入到LoaderManager即可,后续我们会再详细说明。& &这里的另一个重点是parseSchema函数,它的职责是解析图片uri的格式,uri格式为: schema:// + 图片路径,例如网络图片的格式为http://xxx.image.jpg,而本地图片的uri为file:///sdcard/xxx/image.jpg。如果你要实现自己的Loader来加载特定的格式,那么它的uri格式必须以schema://开头,否则解析会错误,例如可以为drawable://image,然后你注册一个schema为&drawable&的Loader到LoaderManager中,SimpleImageLoader在加载图片时就会使用你注册的Loader来加载图片,这样就可以应对用户的多种多样的需求。如果不能拥抱变化那就不能称之为框架了,应该叫功能模块。& & &&本章总结& &最后我们来整理一下这个过程吧,SimpleImageLoader根据用户的配置来配置、启动请求队列,请求队列又会根据用户配置的线程数量来启动几个分发线程。这几个线程不断地从请求队列(线程安全)中读取图片加载请求,并且执行图片加载请求。这些请求是用户通过调用SimpleImageLoader的displayImage函数而产生的,内部会把这个调用封装成一个BitmapRequest对象,并且将该对象添加到请求队列中。这样就有了生产者(用户)和消费者(分发线程),整个SimpleImageLoader就随着CPU跳动而热血沸腾起来了!Github仓库链接&& &&
如果你觉得我写得还行,那就帮我顶个帖吧!Thanks~
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:982328次
积分:12725
积分:12725
排名:第891名
原创:178篇
转载:120篇
译文:23篇
评论:943条
阅读:8703
阅读:26955
阅读:35140
阅读:15927
阅读:13131
文章:10篇
阅读:51892
Android 技术交流群:
(1)(1)(5)(8)(1)(2)(1)(1)(10)(7)(8)(7)(8)(4)(1)(8)(5)(7)(1)(16)(14)(8)(2)(5)(3)(7)(11)(15)(7)(3)(6)(23)(19)(16)(3)(13)(8)(7)(2)(11)(10)(22)(4)Android:ImageLoader(novoda)如何设置图片尺寸
我有一个“照片墙”的功能,需要加载url显示图片。用到了novoda的ImageLoader。问题来了:
// imageloader
protected ImageTagFactory imageTagF
protected ImageManager imageM
protected void initImageLoader() {
imageManager = App.getImageLoader();
imageTagFactory = createImageTagFactory();
protected void setImageTag(ImageView view, String url) {
view.setTag(imageTagFactory.build(url, mContext));
protected void loadImage(ImageView view) {
imageManager.getLoader().load(view);
protected ImageTagFactory createImageTagFactory() {
DisplayMetrics dm = new DisplayMetrics();
mContext.getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthP
ImageTagFactory imageTagFactory = ImageTagFactory.newInstance();
imageTagFactory.setHeight(width);
imageTagFactory.setWidth(width);
imageTagFactory.setDefaultImageResId(R.drawable.ic_launcher);
imageTagFactory.setErrorImageId(R.drawable.ic_launcher);
imageTagFactory.setSaveThumbnail(true);
return imageTagF
这段代码,是ImageLoader几乎所有的代码。给我造成麻烦的,是中间的一句:
imageTagFactory.setHeight(width);
imageTagFactory.setWidth(width); 这两句,是Factory的代码。可以猜想到,肯定是做一些初始化操作需要用到的。但是,我的图片肯定是尺寸个不一样的,无法通过初始化就预先设置好他的尺寸。
我也通过在xml里设置fill_parent和fit_center来尝试修改图片的尺寸。但是失败了。也尝试了在代码里获取图片的对象,手动设置LayoutParams,仍然失败了。好像通过Factory初始化了以后,这个图片的尺寸就不能改变了似的。
我的最终的目的很简单。上图:
我希望这些图片是横向顶满,纵向保持尺寸比例。如果需要更多的代码我再贴。
加载图片的时候,调用2个方法:
setImageTag(ImageView view, String url)
// 设置图片的url
loadImage(ImageView view)
// 加载图片
为什么每次上传了一张图片以后,在文本区写文字就卡死掉了?? 我的图片是经过了压缩的,只有32k。每次我不得不把文字写完了以后,再贴图片上来。这是一个bug么?浏览器:safari8.0,操作系统os x10.10。如果需要的话我录一个视频发给你看
我做过一次类似的功能,我没有在图片加载上下功夫,而是在控件里去设置控件大小,这样的好处是图片比屏幕窄的时候也能填充
--- 共有 1 条评论 ---
我在代码里通过layoutparams设置了 还是不对 还有 我过去屏幕的尺寸方法正确吧? 为什么宽度只有一半
我获取宽度getDefaultDusplay().get出来的。我做法是在imageview的setimage里,geiLayoutParams,然后把设置大小
--- 共有 3 条评论 ---
这是我的代码,不知道对你是否有用:
覆写set就是为了load后设置能够生效。
我也是这样的啊 但是load应该发生在我set之后 load肯定是一个线程 会不会是我set了以后load又给他改回去了
楼主可以看看KJFrameForAndroid这个框架,里面的图片显示可以自定义显示的大小,应该可以解决。
--- 共有 4 条评论 ---
哦哦 好的 我去研究研究
额,不是换,只是让你参考里面的实现方法。
还用到了touchgallery...
又换啊。。。我这个小项目里面应同时用了cube,imageloader了,我已经觉得很恶心了。。。 我再研究研究android ImageLoader加载本地图片的工具类
时间: 16:51:03
&&&& 阅读:31446
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&
import android.widget.ImageV
import com.nostra13.universalimageloader.core.ImageL
* 异步加载本地图片工具类
* @author tony
public class LoadLocalImageUtil {
private LoadLocalImageUtil() {
private static LoadLocalImageUtil instance = null;
public static synchronized LoadLocalImageUtil getInstance() {
if (instance == null) {
instance = new LoadLocalImageUtil();
* 从内存卡中异步加载本地图片
* @param uri
* @param imageView
public void displayFromSDCard(String uri, ImageView imageView) {
// String imageUri = "file:///mnt/sdcard/image.png"; // from SD card
ImageLoader.getInstance().displayImage("file://" + uri, imageView);
* 从assets文件夹中异步加载图片
* @param imageName
图片名称,带后缀的,例如:1.png
* @param imageView
public void dispalyFromAssets(String imageName, ImageView imageView) {
// String imageUri = "assets://image.png"; // from assets
ImageLoader.getInstance().displayImage("assets://" + imageName,
imageView);
* 从drawable中异步加载本地图片
* @param imageId
* @param imageView
public void displayFromDrawable(int imageId, ImageView imageView) {
// String imageUri = "drawable://" + R.drawable. // from drawables
// (only images, non-9patch)
ImageLoader.getInstance().displayImage("drawable://" + imageId,
imageView);
* 从内容提提供者中抓取图片
public void displayFromContent(String uri, ImageView imageView) {
// String imageUri = "content://media/external/audio/albumart/13"; //
// from content provider
ImageLoader.getInstance().displayImage("content://" + uri, imageView);
&标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&原文:/tony-yang-flutter/p/3986157.html
&&国之画&&&& &&&&&&
&& &&&&&&&&&&&&&&
鲁ICP备号-4
打开技术之扣,分享程序人生!}

我要回帖

更多关于 imageloader github 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信