使用Android新式LruCache缓存图片,基于线程池异步加载图片
16lz
2021-12-04
import java.io.BufferedInputStream;import java.io.ByteArrayOutputStream;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Handler;import android.os.Message;import android.support.v4.util.LruCache;import android.util.Log;import android.widget.ImageView;/* * 使用Android新式LruCache缓存图片,基于线程池异步加载图片。 * 基本思路:开辟一个线程池下载网络图片,同时创建一个LruCache作为Android内存缓存混存图片。 * 上层应用传递过来一个URL要求从该URL下载图片时,首先检查LruCache中是否存在以该URL为索引的缓存图片, * 若有,则直接从缓存中读出来返回给上层应用;若没有,此时再开辟线程下载,下载完成后将此bitmap埋入缓存。 * 备注:图片的url作为缓存图片时LruCache的 Key。 * LruCache在内存中的缓存模型为<K,V>。 */public class AsyncImageLoader {private ExecutorService pool;private Handler handler;private ImageLoadedListener listener;private final int WHAT = 0xe001;// 默认的线程池容量private int DEFAULT_TASK_NUMBER = 10;// 网络超时时间:30秒private static int TIMEOUT = 30 * 1000;private LruCache<String, Bitmap> mMemoryCache;// 4MB缓存大小private final int CACHE_SIZE = 4 * 1024 * 1024;public AsyncImageLoader(int asyncTaskNumber) {initialization(asyncTaskNumber);}public AsyncImageLoader() {// 默认的构造函数初始化线程池容量为:TASK_NUMBERinitialization(DEFAULT_TASK_NUMBER);}// 初始化private void initialization(int asyncTaskNumber) {mMemoryCache = new LruCache<String, Bitmap>(CACHE_SIZE) {@Overrideprotected int sizeOf(String key, Bitmap value) {return value.getRowBytes() * value.getHeight();}};// 创建容量为 asyncTaskNumber 的线程池。pool = Executors.newFixedThreadPool(asyncTaskNumber);handler = new Handler() {@Overridepublic void handleMessage(Message message) {switch (message.what) {case WHAT:listener.imageLoaded((Bitmap) message.obj);}}};}// 异步设置一个ImagView的Bitmap(该ImageView的Bitmap从网络加载)// 该方法为public,作为该工具类的外部调用接口。public void asyncSetImageBitmap(String url, final ImageView view) {download(url, new ImageLoadedListener() {@Overridepublic void imageLoaded(Bitmap bitmap) {view.setImageBitmap(bitmap);}});}// 异步的从一个URL下载一个Bitmap。// 下载成功后,回调imageLoaded(Bitmap bitmap, String url);// 该方法为public,作为该工具类的外部调用接口。public void download(String url, ImageLoadedListener listener) {this.listener = listener;// 首先从缓存中检查是否存在以url为key的bitmap。// 若有,则直接从缓存中读取使用,不再使用线程重复加载。Bitmap bmp = mMemoryCache.get(url);if (bmp != null) {Log.d("读取缓存", url + " 已经缓存,无须重复下载!");sendResult(bmp);return;}Thread t = new DownloadThread(url);pool.execute(t);}// 开辟一个下载线程private class DownloadThread extends Thread {private String url;public DownloadThread(String url) {this.url = url;}@Overridepublic void run() {Bitmap bmp = loadBitmapFromURL(url);// 将新的bitmap埋入缓存mMemoryCache.put(url, bmp);sendResult(bmp);}}// 发送消息通知:bitmap已经下载完成。private void sendResult(Bitmap bitmap) {Message message = handler.obtainMessage();message.what = WHAT;message.obj = bitmap;handler.sendMessage(message);}// 回调函数public interface ImageLoadedListener {public void imageLoaded(Bitmap bitmap);}// 给定一个URL,从这个URL下载Bitmappublic static Bitmap loadBitmapFromURL(String url) {if (!url.contains("http://")) {url = "http://" + url;}Log.d("线程:" + Thread.currentThread().getId(), "开始下载: " + url);Bitmap bmp = null;try {byte[] imageBytes = loadRawDataFromURL(url);bmp = BitmapFactory.decodeByteArray(imageBytes, 0,imageBytes.length);} catch (Exception e) {e.printStackTrace();}return bmp;}// 给定一个URL,从这个URL下载原始数据块。public static byte[] loadRawDataFromURL(String u) throws Exception {URL url = new URL(u);HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 配置基础网络链接参数conn.setConnectTimeout(TIMEOUT);conn.setReadTimeout(TIMEOUT);InputStream is = conn.getInputStream();BufferedInputStream bis = new BufferedInputStream(is);ByteArrayOutputStream baos = new ByteArrayOutputStream();final int BUFFER_SIZE = 1024 * 5;final int EOF = -1;int c;byte[] buf = new byte[BUFFER_SIZE];while (true) {c = bis.read(buf);if (c == EOF)break;baos.write(buf, 0, c);}conn.disconnect();is.close();byte[] data = baos.toByteArray();baos.flush();return data;}}
更多相关文章
- android Handler and progress
- android清除缓存并获取大小
- Android(安卓)网络请求不能放在主线程上面
- android studio 57 MP3 音乐播放器 下载网络歌曲 代码
- Android文件下载程序例子
- NDK旧版本下载地址
- Android清理缓存工具类
- android 多线程并发下载文件
- Android之SurfaceView学习一