Android ListView异步加载图片优化
2013-04-01 11:15
423 查看
废话不多说,异步请求多线程。
优化:
1.线程池 2.缓存到内存 3.缓存到SD卡 4.并发下防止重复请求(少数情况下)
主要用到 ExecutorService、SoftReference<Bitmap>、Future<SoftReference<Bitmap>>(防止重复线程请求)、ConcurrentHashMap<String, Future<SoftReference<Bitmap>>>()
其实如果说不存在重复图片也就不存在重复请求问题,这里是根据URL地址来判断图片的唯一性
优化:
1.线程池 2.缓存到内存 3.缓存到SD卡 4.并发下防止重复请求(少数情况下)
主要用到 ExecutorService、SoftReference<Bitmap>、Future<SoftReference<Bitmap>>(防止重复线程请求)、ConcurrentHashMap<String, Future<SoftReference<Bitmap>>>()
package com.cntomorrow.tboing.imageloader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.lang.ref.SoftReference; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import android.annotation.SuppressLint; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Handler; import android.os.Message; import android.util.Log; import android.widget.ImageView; import com.tby.tboing.http.HttpRequestService; public class AsyncBufferImageLoader { private final static String LOG_TAG= "ImageLoader"; private final ConcurrentHashMap<String, Future<SoftReference<Bitmap>>> imageCache = new ConcurrentHashMap<String, Future<SoftReference<Bitmap>>>(); //还是根据手机配置来吧 private ExecutorService executors = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 3); @SuppressLint("SdCardPath") static final private String DIR = "/mnt/sdcard/Demo01/"; public AsyncBufferImageLoader() { } /** * <p> 加载图片</p> * @param imageView * @param imageURL * @param imageCallBack * @param externalLoad 是否允许从SD卡或服务器获取图片 * @return <br><br> * author tboing<BR> * date 2013-4-1<br> * remark <br> */ public Bitmap loadBitmap(final ImageView imageView, final String imageURL, final ImageCallBack imageCallBack, boolean externalLoad) { Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { Log.v(LOG_TAG, "从外部拿到了数据!"); imageCallBack.imageLoad(imageView, (Bitmap)msg.obj, imageURL); super.handleMessage(msg); } }; Future<SoftReference<Bitmap>> f = imageCache.get(imageURL); Bitmap bitmap = null; if (f != null) { Log.v(LOG_TAG, "缓存中有值,从缓存中取!"); SoftReference<Bitmap> reference; try { if (f.isDone()) { // 如果结果已经返回则直接取,不会阻塞 reference = f.get(); bitmap = reference.get(); if (bitmap != null) { Log.v(LOG_TAG, "缓存中取成功!"); return bitmap; } Log.v(LOG_TAG, "缓存中取失败,将从SD卡或者服务器获取!"); imageCache.remove(imageURL, f); // 如果弱引用失效则需要重新去请求 } else { Log.v(LOG_TAG, "已经有线程请求图片,但未完成,请稍后!----------------------"); } } catch (InterruptedException e) { } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(!externalLoad) return null; executors.execute(new RequestImage(imageURL, handler)); return null; } private class RequestImage implements Runnable { private String imageURL; private Handler handler; public RequestImage(String imageURL, Handler handler) { this.imageURL = imageURL; this.handler = handler; } @Override public void run() { Future<SoftReference<Bitmap>> f = null; Bitmap bitmap = null; //如果不需要从SD卡或者NET请求 FutureTask<SoftReference<Bitmap>> ft = new FutureTask<SoftReference<Bitmap>>( new Callable<SoftReference<Bitmap>>() { @Override public SoftReference<Bitmap> call() throws Exception { Bitmap bitmap = readFromSDCard(imageURL); //从SD卡中获取 if (bitmap == null) { Log.v(LOG_TAG, "SD卡中没取着!"); // 如果不在内存缓存中,也不在本地(被jvm回收掉),则开启线程下载图片 HttpRequestService httpRequest = new HttpRequestService(); try { bitmap = httpRequest.requestBitmap(imageURL); Thread.sleep(1000); if (bitmap != null) { writeToSDCard(imageURL, bitmap); //写入SD卡 } } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } return new SoftReference<Bitmap>(bitmap); } }); //防止并发覆盖 f = imageCache.putIfAbsent(imageURL, ft); if (f == null) { f = ft; ft.run(); } else { Log.v(LOG_TAG, "其他线程正在请求!--------------------"); } try { bitmap = f.get().get(); } catch (Exception e) { imageCache.remove(imageURL, ft); e.printStackTrace(); } sendMessage(bitmap); } private void sendMessage(Bitmap bitmap) { Message msg = handler.obtainMessage(0, bitmap); handler.sendMessage(msg); } } private Bitmap readFromSDCard(String imageURL) { String bitmapName = imageURL .substring(imageURL.lastIndexOf("/") + 1); File cacheDir = new File(DIR); File[] cacheFiles = cacheDir.listFiles(); if(cacheFiles != null) { int i = 0; for (; i < cacheFiles.length; i++) { if (bitmapName.equals(cacheFiles[i].getName())) { break; } } if (i < cacheFiles.length) { return BitmapFactory.decodeFile(DIR + bitmapName); } } return null; } private void writeToSDCard(String imageURL, Bitmap bitmap) { File dir = new File(DIR); if (!dir.exists()) { dir.mkdirs(); } File bitmapFile = new File(DIR + imageURL.substring(imageURL.lastIndexOf("/") + 1)); if (!bitmapFile.exists()) { try { bitmapFile.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } FileOutputStream fos; try { fos = new FileOutputStream(bitmapFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 回调接口 * * @author onerain * */ public interface ImageCallBack { public void imageLoad(ImageView imageView, Bitmap bitmap, String url); } public void shutdown() { if(executors != null) { executors.shutdown(); executors = null; } imageCache.clear(); } }
其实如果说不存在重复图片也就不存在重复请求问题,这里是根据URL地址来判断图片的唯一性
相关文章推荐
- listview异步图片加载之优化篇(android)
- Android之ListView异步加载网络图片(优化缓存机制)
- Android之ListView异步加载网络图片(优化缓存机制)
- android中ListView性能优化异步加载图片 使滑动效果流畅
- Android之ListView异步加载网络图片(优化缓存机制) .
- Android之ListView异步加载网络图片(优化缓存机制)
- Android进阶:ListView性能优化异步加载图片 使滑动效果流畅
- 又优化了一下 Android ListView 异步加载图片
- 又优化了一下 Android ListView 异步加载图片
- 又优化了一下 Android ListView 异步加载图片
- Android之ListView异步加载网络图片(优化缓存机制)
- Android 解决ListView异步加载网络数据(图片文字)出现位置错乱以及优化ListView的加载
- 进一步优化Android ListView GridView中异步加载图片
- Android之ListView异步加载网络图片(优化缓存机制)
- Android之ListView异步加载网络图片(优化缓存机制)
- wemall app商城源码Android之ListView异步加载网络图片(优化缓存机制)
- 优化 Android ListView 异步加载图片
- 又优化了一下 Android ListView 异步加载图片
- 又优化了一下Android ListView 异步加载图片(续)
- Android之ListView异步加载网络图片(优化缓存机制)