imageloader源码解析

 

使用方式就不说了、直接源码分析:

一、ImageLoader分析(供上层调用,提供同步、异步加载方式)

public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,
      ImageSize targetSize, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
   //检测配置信息、相关类:ImageLoaderConfiguration
   checkConfiguration();
   if (imageAware == null) {
      throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS);
   }
   if (listener == null) {
      listener = defaultListener;
   }
   if (options == null) {
      options = configuration.defaultDisplayImageOptions;
   }

   //若地址未空,则取消线程,显示默认加载图片、并回调
   if (TextUtils.isEmpty(uri)) {
      engine.cancelDisplayTaskFor(imageAware);
      listener.onLoadingStarted(uri, imageAware.getWrappedView());
      if (options.shouldShowImageForEmptyUri()) {
         imageAware.setImageDrawable(options.getImageForEmptyUri(configuration.resources));
      } else {
         imageAware.setImageDrawable(null);
      }
      listener.onLoadingComplete(uri, imageAware.getWrappedView(), null);
      return;
   }
//根据获取目标view的大小,换算出所需的内存,并加入ImageLoaderEngine类中的cacheKeysForImageAwares队列
if (targetSize == null) {
   targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, configuration.getMaxImageSize());
}
String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);
engine.prepareDisplayTaskFor(imageAware, memoryCacheKey);

//判断内存是否有缓存,若有启用ProcessAndDisplayImageTask线程加载图片
//否则使用LoadAndDisplayImageTask线程加载图片
//并提交给ImageLoaderEngine的线程池对象执行

Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);
if (bmp != null && !bmp.isRecycled()) {
   L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey);

   if (options.shouldPostProcess()) {
      ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,
            options, listener, progressListener, engine.getLockForUri(uri));
      ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo,
            defineHandler(options));
      if (options.isSyncLoading()) {
         displayTask.run();
      } else {
         engine.submit(displayTask);
      }
   } else {
      options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE);
      listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp);
   }
} else {
   if (options.shouldShowImageOnLoading()) {
      imageAware.setImageDrawable(options.getImageOnLoading(configuration.resources));
   } else if (options.isResetViewBeforeLoading()) {
      imageAware.setImageDrawable(null);
   }

   ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,
         options, listener, progressListener, engine.getLockForUri(uri));
   LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo,
         defineHandler(options));
   if (options.isSyncLoading()) {
      displayTask.run();
   } else {
      engine.submit(displayTask);
   }
}

二、ImageLoaderEngine分析( 三个线程池、利用ReentrantLock(重入锁)和AtomicBoolean(原子)来解决多线程访问)

private Executor taskExecutor;//加载网络图片的线程池
private Executor taskExecutorForCachedImages;//加载文件缓存和内存缓存的线程池
private Executor taskDistributor;//判断是否有文件缓存、并确定使用taskExecutor还是taskExecutorForCachedImages加载图片
三、ImageLoaderConfiguration分析( 主要是内存大小、队列请求方式、线程优先级等配置,提供三种加载方式)

1、downloader(默认网络加载、用InputStream实现)

  2、networkDeniedDownloader(非网络加载)

  3、slowNetworkDownloader(弱网加载、继承FilterInputStream,重写skip方法。注:因为InputStream的skip方法有最少值限制、所以当弱网下载时、可能会中断)

inputStream 源码:

public long skip(long n) throws IOException {

    long remaining = n;
    int nr;

    if (n <= 0) {
        return 0;
    }

    int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
    byte[] skipBuffer = new byte[size];
    while (remaining > 0) {
        nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
        if (nr < 0) {
            break;
        }
        remaining -= nr;
    }

    return n - remaining;
}

FilterInputStream源码:

@Override
public long skip(long n) throws IOException {
   long totalBytesSkipped = 0L;
   while (totalBytesSkipped < n) {
      long bytesSkipped = in.skip(n - totalBytesSkipped);
      if (bytesSkipped == 0L) {
         int by_te = read();
         if (by_te < 0) {
            break; // we reached EOF
         } else {
            bytesSkipped = 1; // we read one byte
         }
      }
      totalBytesSkipped += bytesSkipped;
   }
   return totalBytesSkipped;
}

四、LoadAndDisplayImageTask分析(使用ReentrantLock重入锁来确保加载成功后不错位)

执行线程、sync true为同步、false为异步
static void runTask(Runnable r, boolean sync, Handler handler, ImageLoaderEngine engine) {
		if (sync) {
			r.run();
		} else if (handler == null) {
			engine.fireCallback(r);
		} else {
			handler.post(r);
		}
	}

 

五、其他

继承BitmapDisplayer实现不同的显示方式、圆角、裁剪等

cache包下提供若干个缓存方式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值