ImageLoader.java类是加载网络中的图片,并将图片保存到本地,也可以将图片设置到对应的控件中。

package com.example.image;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentLinkedQueue;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.widget.ImageView;import com.example.R;import com.example.http.HttpHelper;import com.example.http.HttpHelper.HttpResult;import com.example.manage.ThreadManager;import com.example.manage.ThreadManager.ThreadPoolProxy;import com.example.utils.DrawableUtils;import com.example.utils.FileUtils;import com.example.utils.IOUtils;import com.example.utils.LogUtils;import com.example.utils.StringUtils;import com.example.utils.SystemUtils;import com.example.utils.UIUtils;/** * Created by mwqi on 2014/6/8. */public class ImageLoader {/** 图片下载的线程池名称 */public static final String THREAD_POOL_NAME = "IMAGE_THREAD_POOL";/** 图片缓存最大数量 */public static final int MAX_DRAWABLE_COUNT = 100;/** 图片的KEY缓存 */private static ConcurrentLinkedQueue<String> mKeyCache =  new ConcurrentLinkedQueue<String>();/** 图片的缓存 */private static Map<String, Drawable> mDrawableCache = new ConcurrentHashMap<String, Drawable>();private static BitmapFactory.Options mOptions = new BitmapFactory.Options();/** 图片下载的线程池 */private static ThreadPoolProxy mThreadPool = ThreadManager.getSinglePool(THREAD_POOL_NAME);/** 用于记录图片下载的任务,以便取消 */private static ConcurrentHashMap<String, Runnable> mMapRuunable = new ConcurrentHashMap<String, Runnable>();/** 图片的总大小 */private static long mTotalSize;static {mOptions.inDither = false;// 设置为false,将不考虑图片的抖动值,这会减少图片的内存占用mOptions.inPurgeable = true;// 设置为ture,表示允许系统在内存不足时,删除bitmap的数组。mOptions.inInputShareable = true;// 和inPurgeable配合使用,如果inPurgeable是false,那么该参数将被忽略,表示是否对bitmap的数组进行共享}/** 加载图片 */public static void load(ImageView view, String url) {if (view == null || StringUtils.isEmpty(url)) {return;}view.setTag(url);//把控件和图片的url进行绑定,因为加载是一个耗时的,等加载完毕了需要判定该控件是否和该url匹配Drawable drawable = loadFromMemory(url);//从内存中加载if (drawable != null) {setImageSafe(view, url, drawable);//如果内存中加载到了,直接设置图片} else {view.setImageResource(R.drawable.ic_default);//如果没加载到,设置默认图片,并异步加载asyncLoad(view, url);}}/** 异步加载 */private static void asyncLoad(final ImageView view, final String url) {//先创建一个runnable封装执行过程Runnable runnable = new Runnable() {@Overridepublic void run() {mMapRuunable.remove(url);Drawable drawable = loadFromLocal(url);if (drawable == null) {drawable = loadFromNet(url);}if (drawable != null) {setImageSafe(view, url, drawable);}}};cancel(url);//先取消这个url的下载mMapRuunable.put(url, runnable);//记住这个runnable,以便后面取消mThreadPool.execute(runnable);//执行任务}/** 取消下载 */public static void cancel(String url) {Runnable runnable = mMapRuunable.remove(url);//根据url来获取指定的runnableif (runnable != null) {mThreadPool.cancel(runnable);//从线程池中删除该任务,如果任务已经开始下载了,就无法删除}}/** 从内存中加载 */private static Drawable loadFromMemory(String url) {Drawable drawable = mDrawableCache.get(url);if (drawable != null) {//从内存中获取到了,需要重新放到内存队列的最后,以便满足LRC//一般缓存算法有两种,第一是LFU,按使用次数来判定删除优先级,使用次数最少的最先删除//还有一个就是LRC,就是按最后使用时间来判定删除优先级,最后使用时间越早的最先删除addDrawableToMemory(url, drawable);}return drawable;}/** 从本地设备中加载 */private static Drawable loadFromLocal(String url) {Bitmap bitmap = null;Drawable drawable = null;String path = FileUtils.getIconDir();FileInputStream fis = null;try {//获取流fis = new FileInputStream(new File(path + url));if (fis != null) {// BitmapFactory.decodeByteArray(data, offset, length)// BitmapFactory.decodeFile(pathName)// BitmapFactory.decodeStream(is)// 上面三个分析源码可知,他们都是在Java层创建byte数组,然后把数据传递给本地代码。// 下面这个是把文件描述符传递给本地代码,由本地代码去创建图片// 优点,由于是本地代码创建的,那么byte数组的内存占用不会算到应用内存中,并且一旦内存不足,将会把bitmap的数组回收掉,而bitmap不会被回收// 当显示的时候,发现bitmap的数组为空时,将会再次根据文件描述符去加载图片,此时可能由于加载耗时造成界面卡顿,但总比OOM要好得多。// 由于本地代码在创建图片时,没有对图片进行校验,所以如果文件不完整,或者根本就不是一个图片时,系统也不会报错,仍然会返回一个bitmap,但是这个bitmap是一个纯黑色的bitmap。// 所以我们在下载图片的时候,一定要先以一个临时文件下载,等下载完毕了,再对图片进行重命名。bitmap = BitmapFactory.decodeFileDescriptor(fis.getFD(), null, mOptions);}if (null != bitmap) {//把bitmap转换成drawabledrawable = new BitmapDrawable(UIUtils.getResources(), bitmap);}if (drawable != null) {//放到内存缓存队列中addDrawableToMemory(url, drawable);}} catch (OutOfMemoryError e) {mKeyCache.clear();mDrawableCache.clear();LogUtils.e(e);} catch (Exception e) {LogUtils.e(e);} finally {IOUtils.close(fis);}return drawable;}/** 从网络加载图片 */private static Drawable loadFromNet(String url) {HttpResult httpResult = HttpHelper.download(HttpHelper.URL + "image?name=" + url);InputStream stream = null;if (httpResult == null || (stream = httpResult.getInputStream()) == null) {//请求网络return null;}String tempPath = FileUtils.getIconDir() + url + ".temp";String path = FileUtils.getIconDir() + url;FileUtils.writeFile(stream, tempPath, true);//把网络下载保存在本地if (httpResult != null) {//关闭网络连接httpResult.close();}FileUtils.copy(tempPath, path, true);//进行改名return loadFromLocal(url);//从本地加载}/** 添加到内存 */private static void addDrawableToMemory(String url, Drawable drawable) {mKeyCache.remove(url);mDrawableCache.remove(url);//如果大于等于100张,或者图片的总大小大于应用总内存的四分之一先删除前面的while (mKeyCache.size() >= MAX_DRAWABLE_COUNT || mTotalSize >= SystemUtils.getOneAppMaxMemory() / 4) {String firstUrl = mKeyCache.remove();Drawable remove = mDrawableCache.remove(firstUrl);mTotalSize -= DrawableUtils.getDrawableSize(remove);}mKeyCache.add(url);//添加mDrawableCache.put(url, drawable);mTotalSize += DrawableUtils.getDrawableSize(drawable);}/** 设置给控件图片 */private static void setImageSafe(final ImageView view, final String url, final Drawable drawable) {if (drawable == null && view.getTag() == null) {return;}UIUtils.runInMainThread(new Runnable() {//需要在主线程中设置@Overridepublic void run() {Object tag;//在主线程中判断,可以做到同步if ((tag = view.getTag()) != null) {String str = (String) tag;if (StringUtils.isEquals(str, url)) {//检测如果url和控件匹配view.setImageDrawable(drawable);//就进行图片设置}}}});}}


更多相关文章

  1. Android(安卓)圆角图片的实现
  2. Android中的WebView详解
  3. Android实现ViewPager无限循环效果(二)
  4. Android(安卓)获取最新图片
  5. 实战 QQ demo (学习 android 先来个QQ)
  6. 关于Android(安卓)Studio安装完后activity_main.xml前几行报错的
  7. 科普篇
  8. android 通过webservice方式向服务器上传图片
  9. Android平台上利用opencv进行图像的缩放

随机推荐

  1. [Android] AutoCompleteTextView:自动完成
  2. android:windowSoftInputMode
  3. android的PowerManager和PowerManager.Wa
  4. 关于Android初学者的学习线路的相关知识
  5. Android自动挂断电话
  6. android渐变色,边角,边框,
  7. Android开发笔记——以Volley图片加载、
  8. Android(安卓)使用NDK R5开发JNI应用详解
  9. Android(安卓)Studio 单元测试(instrument
  10. Android生命周期和启动模式