使用LruCache和DiskLruCache来下载图片
LruCache是一个很好用的图片缓存工具:
主要做法是:滑动图片时将图片的bitmap缓存在LruCache<String, Bitmap>中,退出程序后将图片缓存进文件里,采用DiskLruCache mDiskLruCache
所以我们必须设置一个图片缓存的地址:
- public void setImageCache(){
- String strPath = null;
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- File sdFile = Environment.getExternalStorageDirectory();
- strPath = sdFile.getAbsolutePath() + "/pic/";
- File cacheFile = new File(strPath);
- if(!cacheFile.exists()){
- cacheFile.mkdir();
- }
- }
- else{
- String strCacheDir = this.getCacheDir().getAbsolutePath();
- strPath = strCacheDir + "/pic/";
- }
- setCachePath(strPath);
- }
- private void setCachePath(String strPicCachePath){
- if(TextUtils.isEmpty(strPicCachePath)){
- return;
- }
- m_strPicCachePath = strPicCachePath;
- File cacheFile = new File(strPicCachePath);
- if(!cacheFile.exists()){
- cacheFile.mkdir();
- }
- }
- public String getCacheBmpPath(String strUrl){
- if(TextUtils.isEmpty(m_strPicCachePath) || TextUtils.isEmpty(strUrl)){
- return "";
- }
- return m_strPicCachePath + StringUtil.MD5Encode(strUrl) + mFileExName;//".bmp";
- }
然后写List的adapter:
- private class ListAdapter extends BaseAdapter implements OnScrollListener {
- protected List<ShopData> items = new ArrayList<ShopData>();
- protected static final int FETCH_IMAGE_MSG = 1;
- private LruCache<String, Bitmap> mMemoryCache;
- protected HashSet<ImageView> mItemsMissingImages = new HashSet<ImageView>();
- protected ImageLoaderHandler mHandler;
- protected ImageLoader mImageFetcher;
- public static final int TIMEOUT = 30000;//超时时间30秒
- private DiskLruCache mDiskLruCache;
- public ListAdapter() {
- super();
- mHandler = new ImageLoaderHandler();
- int maxMemory = (int) Runtime.getRuntime().maxMemory();
- int mCacheSize = maxMemory / 8;
- // 给LruCache分配1/8 4M
- mMemoryCache = new LruCache<String, Bitmap>(mCacheSize) {
- // 必须重写此方法,来测量Bitmap的大小
- @Override
- protected int sizeOf(String key, Bitmap value) {
- return value.getRowBytes() * value.getHeight();
- }
- };
- try {
- mDiskLruCache = DiskLruCache
- .open(new File(m_strPicCachePath), getAppVersion(MainActivityTest.this), 1, 10 * 1024 * 1024);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /**
- * 将缓存记录同步到journal文件中。
- */
- public void fluchCache() {
- if (mDiskLruCache != null) {
- try {
- mDiskLruCache.flush();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- @Override
- public int getCount() {
- return items.size();
- }
- @Override
- public Object getItem(int position) {
- return items.get(position);
- }
- @Override
- public long getItemId(int position) {
- return position;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- ShopDataTag tag = new ShopDataTag();
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.listitem, null);
- tag.name = (TextView) convertView.findViewById(R.id.name);
- tag.shopInfo = (TextView) convertView.findViewById(R.id.info);
- tag.icon = (ImageView) convertView.findViewById(R.id.image_icon);
- convertView.setTag(tag);
- } else {
- tag = (ShopDataTag) convertView.getTag();
- }
- TextView name = tag.name;
- TextView info = tag.shopInfo;
- ImageView imageView = tag.icon;
- ShopData data = items.get(position);
- name.setText(data.name);
- info.setText(data.info);
- imageView.setTag(data.url);
- setContactPhoto(data.url, imageView);
- return convertView;
- }
- protected void setContactPhoto(String url,ImageView viewToUse) {
- if(TextUtils.isEmpty(url)) {
- viewToUse.setImageResource(R.drawable.avatar);
- }else{
- //先看mMemoryCache里能不能得到bitmap
- Bitmap bitmap = mMemoryCache.get(url);
- if (bitmap != null) {
- viewToUse.setImageBitmap(bitmap);
- } else {
- Snapshot snapShot = null;
- FileDescriptor fileDescriptor = null;
- FileInputStream fileInputStream = null;
- try {
- //因为mDiskLruCache会把key作为文件名,所以把url通过md5转换为key
- final String key = hashKeyForDisk(url);
- snapShot = mDiskLruCache.get(key);
- //如果snapShot为空,就是没找到对应的文件
- if (snapShot == null) {
- //这里去下载
- fetchImage(viewToUse);
- }else{
- fileInputStream = (FileInputStream) snapShot.getInputStream(0);
- fileDescriptor = fileInputStream.getFD();
- if (fileDescriptor != null) {
- bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
- }
- //如果解析文件成bitmap失败,重新下载
- if(!TextUtils.isEmpty(url) && bitmap != null){
- mMemoryCache.put(url, bitmap);
- viewToUse.setImageBitmap(bitmap);
- }else{
- fetchImage(viewToUse);
- }
- }
- }catch(IOException ex) {
- ex.printStackTrace();
- }finally{
- if (fileDescriptor == null && fileInputStream != null) {
- try {
- fileInputStream.close();
- } catch (IOException e) {
- }
- }
- }
- }
- }
- }
- private void fetchImage(ImageView viewToUse) {
- viewToUse.setImageResource(R.drawable.avatar);
- mItemsMissingImages.add(viewToUse);
- if (mScrollState != OnScrollListener.SCROLL_STATE_FLING) {
- sendFetchImageMessage(viewToUse);
- }
- }
- public String <strong>hashKeyForDisk</strong>(String key) { 将key转换为md5文件
- return StringUtil.MD5Encode(key);
- }
- // image downloader
- private class ImageLoaderHandler extends Handler {
- @Override
- public void handleMessage(Message message) {
- if (isFinishing()) {
- return;
- }
- switch (message.what) {
- case FETCH_IMAGE_MSG: {
- final ImageView imageView = (ImageView) message.obj;
- if (imageView == null) {
- break;
- }
- final String url = (String) imageView.getTag();
- if (TextUtils.isEmpty(url)) {
- break;
- }
- Bitmap map = getBitmapFromMemCache(url);
- if (map == null) {
- break;
- }
- synchronized (imageView) {
- final String myUrl = (String) imageView.getTag();
- if (TextUtils.equals(url, myUrl)) {
- imageView.setImageBitmap(map);
- mItemsMissingImages.remove(imageView);
- } else {
- }
- }
- break;
- }
- }
- }
- public void clearImageFecthing() {
- removeMessages(FETCH_IMAGE_MSG);
- }
- }
- private class ImageLoader implements Runnable {
- String url;
- private ImageView mImageView;
- public ImageLoader(String url, ImageView imageView) {
- this.url = url;
- this.mImageView = imageView;
- }
- public void run() {
- if (isFinishing()) {
- return;
- }
- if (Thread.interrupted()) {
- return;
- }
- FileDescriptor fileDescriptor = null;
- FileInputStream fileInputStream = null;
- Snapshot snapShot = null;
- try {
- final String key = hashKeyForDisk(url);
- snapShot = mDiskLruCache.get(key);
- if (snapShot == null) {
- // 如果没有找到对应的缓存,则准备从网络上请求数据,并写入缓存
- DiskLruCache.Editor editor = mDiskLruCache.edit(key);
- if (editor != null) {
- OutputStream outputStream = editor.newOutputStream(0);
- boolean flag = downloadImage(url, outputStream);
- if (flag) {
- editor.commit();
- } else {
- editor.abort();
- }
- }
- // 缓存被写入后,再次查找key对应的缓存
- snapShot = mDiskLruCache.get(key);
- }
- //这里应该删除对应的文件
- if (snapShot != null) {
- fileInputStream = (FileInputStream) snapShot.getInputStream(0);
- fileDescriptor = fileInputStream.getFD();
- }
- // 将缓存数据解析成Bitmap对象
- Bitmap bitmap = null;
- if (fileDescriptor != null) {
- bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
- }
- if (bitmap != null) {
- // 将Bitmap对象添加到内存缓存当中
- mMemoryCache.put(url, bitmap);
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (fileDescriptor == null && fileInputStream != null) {
- try {
- fileInputStream.close();
- } catch (IOException e) {
- }
- }
- }
- if (Thread.interrupted()) {
- return;
- }
- Message msg = new Message();
- msg.what = FETCH_IMAGE_MSG;
- msg.obj = mImageView;
- mHandler.sendMessage(msg);
- }
- }
- public Bitmap getBitmapFromMemCache(String key) {
- return mMemoryCache.get(key);
- }
- public boolean downloadImage(String strUrl,OutputStream fos) {
- URL getUrl = null;
- Bitmap bitmap = null;
- BufferedOutputStream out = null;
- BufferedInputStream in = null;
- try {
- getUrl = new URL(strUrl);
- } catch (MalformedURLException ex) {
- Log.e("HttpUtil", "get MalformedURL", ex);
- return false;
- }
- InputStream input = null;
- HttpURLConnection conn = null;
- try {
- conn = (HttpURLConnection)getUrl.openConnection();
- conn.setConnectTimeout(TIMEOUT);
- conn.setReadTimeout(TIMEOUT);
- conn.setDoInput(true);
- conn.connect();
- input = conn.getInputStream();
- in = new BufferedInputStream(input, 8 * 1024);
- out = new BufferedOutputStream(fos, 8 * 1024);
- int b;
- while ((b = in.read()) != -1) {
- out.write(b);
- }
- return true;
- } catch (Exception ex) {
- Log.e("HttpUtil", "downloadImage", ex);
- } catch(OutOfMemoryError ex){
- ex.printStackTrace();
- } finally {
- try {
- if(out != null){
- out.close();
- out = null;
- }
- if (in != null){
- in.close();
- in = null;
- }
- if (conn != null){
- conn.disconnect();
- conn = null;
- }
- } catch (Exception ex) {
- Log.e("HttpUtil", "downloadImage finally", ex);
- }
- }
- return false;
- }
- private boolean getResponse(InputStream input, OutputStream os, byte[] data) throws IOException{
- if(input == null || os == null || data == null){
- return false;
- }
- int i = 0;
- while( (i = input.read(data)) != -1){
- os.write(data, 0, i);
- os.flush();
- }
- os.flush();
- return true;
- }
- private void processMissingImageItems(AbsListView view) {
- for (ImageView iv : mItemsMissingImages) {
- sendFetchImageMessage(iv);
- }
- }
- protected void sendFetchImageMessage(ImageView view) {
- final String url = (String) view.getTag();
- if (TextUtils.isEmpty(url)) {
- return;
- }
- mImageFetcher = new ImageLoader(url, view);
- synchronized (MainActivityTest.this) {
- if (sImageFetchThreadPool == null) {
- sImageFetchThreadPool = Executors.newFixedThreadPool(3);
- }
- sImageFetchThreadPool.execute(mImageFetcher);
- }
- }
- public void clearImageFetching() {
- synchronized (MainActivityTest.this) {
- if (sImageFetchThreadPool != null) {
- sImageFetchThreadPool.shutdownNow();
- sImageFetchThreadPool = null;
- }
- }
- mHandler.clearImageFecthing();
- }
- public void clearMessages() {
- if (mHandler != null) {
- try {
- mHandler.removeCallbacksAndMessages(null);
- } catch (java.lang.Throwable th) {
- }
- mHandler = null;
- }
- }
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- mScrollState = scrollState;
- if (scrollState == OnScrollListener.SCROLL_STATE_FLING) {
- clearImageFetching();
- } else {
- processMissingImageItems(view);
- }
- }
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
- }
- }
- private class ShopDataTag {
- TextView name;
- TextView shopInfo;
- ImageView icon;
- }
效果图:

浙公网安备 33010602011771号