android 图片异步下载 缓存处理 自定义ImageView

 2)BitmapCache.java,  好久没有过来博客园了,今天项目里面使用到了图片传输,后来便自己琢磨了一下,最后通过查阅相关资料,做了一个自定义imageview,其可以实现只要传输给其图片路径,

其它的事就全部交给它处理了,不用再去管什么自己写handler+message,或者使用异步的类.使用起来也非常简单。当然希望有朋友有更好一些的改进,欢迎交流。

 

 

现在我就来介绍一下这个自定义的imageview,它主要使用要的文件有如下的几个:

1)AsyImageLoad.java    2)BitmapCache.java,   3)ImageFileCache.java,  4)ImageGetFromHttp.java

5)回调接口
    public interface doCallback
    {
    /**
    * 回调传输下载 下来后的值
    * @param bitmap
    */
    void doPostBack(Bitmap bitmap);
    }

 7)自定义的ImageView --->myImageView

 

 1)AsyImageLoad.java  

package com.yitu.Util;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import com.df.dianping.R;
import com.yitu.Util.ImageGetFromHttp.FlushedInputStream;
import com.yitu.Util.ImageGetFromHttp.doCallback;
/**
 * 自定义异步任务
 */
public class AnsyImageLoad extends AsyncTask<String,Void, Bitmap>
{
private static final String LOG_TAG = "AnsyImageLoad";
doCallback doback;
String url="";
Context mycontext;
public AnsyImageLoad(String url, doCallback doback2,Context context) {
// TODO Auto-generated constructor stub
this.url=url;
this.doback=doback2;
this.mycontext=context;
}
@Override
protected void onCancelled() {
// TODO Auto-generated method stub
super.onCancelled();
}
@Override
protected void onPostExecute(Bitmap result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
   this.doback.doPostBack(result); //doback(result);
   Log.i("net", "执行任务回调--->取到一个远程数据");
}
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
//拿到一个默认图片
Log.i("net", "初始化执行任务--->取到一个本地数据");
this.doback.doPostBack(null);
}
@Override
protected Bitmap doInBackground(String... arg0) {
// TODO Auto-generated method stub
if(url.equals(""))
{
//返回默认图标icon
//返回默认图片
this.doback.doPostBack(BitmapFactory.decodeResource(mycontext.getResources(), R.drawable.icon));
}
else
{
       final HttpClient client = new DefaultHttpClient();
       final HttpGet getRequest = new HttpGet(arg0[0]);  
try
{
   
       HttpResponse response = client.execute(getRequest);
           final int statusCode = response.getStatusLine().getStatusCode();
           if (statusCode != HttpStatus.SC_OK) {
               Log.i("image_load", "Error " + statusCode + " while retrieving bitmap from " + url);
               return null;
           }
           final HttpEntity entity = response.getEntity();
           if (entity != null) {
               InputStream inputStream = null;
               try {
                   inputStream = entity.getContent();
                   FilterInputStream fit = new FlushedInputStream(inputStream);
                   Log.i("net", "执行任务完毕--->取到一个远程数据--->"+arg0[0]);
                   return BitmapFactory.decodeStream(fit);
               } finally {
                   if (inputStream != null) {
                       inputStream.close();
                       inputStream = null;
                   }
                   entity.consumeContent();
               }
           }
}
        catch (IOException e) {
            getRequest.abort();
            Log.w("net", "I/O error while retrieving bitmap from " + url, e);
        } catch (IllegalStateException e) {
            getRequest.abort();
            Log.w("net", "Incorrect URL: " + url);
        } catch (Exception e) {
            getRequest.abort();
            Log.w("net", "Error while retrieving bitmap from " + url, e);
        } finally {
            client.getConnectionManager().shutdown();
        }
//this.doPostBack(bitmap)
//返回真实图片
}
//return BitmapFactory.decodeResource(mycontext.getResources(), R.drawable.icon);
return null;
}
}

 

 2)BitmapCache.java, 

 

 package com.yitu.Util;


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import com.df.dianping.R;
import com.yitu.Util.ImageGetFromHttp.doCallback;

/**
 * @author wsf
 * 2013-8-13 20:45
 * 用于缓存Bitmap
 * 使用方法
 * 
 */
public class BitmapCache implements doCallback {
public Context mycontext;
public ImageMemoryCache memoryCache=null;
public ImageGetFromHttp fromhttp=null;
public ImageFileCache fileCache=null;
Bitmap result;
/*** 获得一张图片,从三个地方获取,首先是内存缓存,然后是文件缓存,最后从网络获取 ***/
public void setBitmap(final String url,Context context,final doCallback docallback) {
this.mycontext=context;
InitCatch(context);
   // 从内存缓存中获取图片
   result = memoryCache.getBitmapFromCache(url);
   if (result == null) {
       // 文件缓存中获取
       result = fileCache.getImage(url);
       if (result == null) {
        /**
        * 此处为wsf添加代码 
        */        
        AnsyImageLoad imageload=new AnsyImageLoad(url,
        new doCallback() {
@Override
public void doPostBack(Bitmap bitmap) {
// TODO Auto-generated method stub
Log.i("net", "被执行了一次--->docallback");
result=bitmap;
if(bitmap!=null)
{
               fileCache.saveBitmap(result, url);
               memoryCache.addBitmapToCache(url, result);
               docallback.doPostBack(bitmap);
}
else
{
docallback.doPostBack(BitmapFactory.decodeResource(mycontext.getResources(), R.drawable.icon));
}
}
},context);
        imageload.execute(url);
        /**
        * 以上为wsf添加代码 
        */
       } else {
           // 添加到内存缓存
           memoryCache.addBitmapToCache(url, result);
       }
   }
   docallback.doPostBack(result);
}
/**
* 初始化数据
* @param context
*/
public void InitCatch(Context context)
{
memoryCache=new ImageMemoryCache(context);
fromhttp=new ImageGetFromHttp();
fileCache=new ImageFileCache();
}
/**
* 执行结束时回调方法
*/
@Override
public void doPostBack(Bitmap bitmap) {
// TODO Auto-generated method stub
}

    /** 将url转成文件名 **/
    private String convertUrlToFileName(String url) {
        String[] strs = url.split("/");
        return strs[strs.length - 1] + ".cach";
    }
}

 

 3)ImageFileCache.java,

 

 package com.yitu.Util;


import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Comparator;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;
/**
 * http://keegan-lee.diandian.com/post/2012-12-06/40047548955
 * @author wsf
 *
 */
public class ImageFileCache {

    private static final String CACHDIR = "ImgCach";
    private static final String WHOLESALE_CONV = ".cach";
                                                            
    private static final int MB = 1024*1024;
    private static final int CACHE_SIZE = 10;
    private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 10;
                                                                
    public ImageFileCache() {
        //清理文件缓存
        removeCache(getDirectory());
    }
                                                                
    /** 从缓存中获取图片 **/
    public Bitmap getImage(final String url) {    
        final String path = getDirectory() + "/" + convertUrlToFileName(url);
        File file = new File(path);
        if (file.exists()) {
            Bitmap bmp = BitmapFactory.decodeFile(path);
            if (bmp == null) {
                file.delete();
            } else {
                updateFileTime(path);
                return bmp;
            }
        }
        return null;
    }
                                                                
    /** 将图片存入文件缓存 **/
    public void saveBitmap(Bitmap bm, String url) {
        if (bm == null) {
            return;
        }
        //判断sdcard上的空间
        if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
            //SD空间不足
            return;
        }
        String filename = convertUrlToFileName(url);
        String dir = getDirectory();
        File dirFile = new File(dir);
        if (!dirFile.exists())
            dirFile.mkdirs();
        File file = new File(dir +"/" + filename);
        try {
            file.createNewFile();
            OutputStream outStream = new FileOutputStream(file);
            bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
            outStream.flush();
            outStream.close();
        } catch (FileNotFoundException e) {
            Log.w("ImageFileCache", "FileNotFoundException");
        } catch (IOException e) {
            Log.w("ImageFileCache", "IOException");
        }
    } 
                                                                
    /**
     * 计算存储目录下的文件大小,
     * 当文件总大小大于规定的CACHE_SIZE或者sdcard剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定
     * 那么删除40%最近没有被使用的文件
     */
    private boolean removeCache(String dirPath) {
        File dir = new File(dirPath);
        File[] files = dir.listFiles();
        if (files == null) {
            return true;
        }
        if (!android.os.Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED)) {
            return false;
        }
                                                            
        int dirSize = 0;
        for (int i = 0; i < files.length; i++) {
            if (files[i].getName().contains(WHOLESALE_CONV)) {
                dirSize += files[i].length();
            }
        }
                                                            
        if (dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
            int removeFactor = (int) ((0.4 * files.length) + 1);
            Arrays.sort(files, new FileLastModifSort());
            for (int i = 0; i < removeFactor; i++) {
                if (files[i].getName().contains(WHOLESALE_CONV)) {
                    files[i].delete();
                }
            }
        }
                                                            
        if (freeSpaceOnSd() <= CACHE_SIZE) {
            return false;
        }
                                                                    
        return true;
    }
                                                                
    /** 修改文件的最后修改时间 **/
    public void updateFileTime(String path) {
        File file = new File(path);
        long newModifiedTime = System.currentTimeMillis();
        file.setLastModified(newModifiedTime);
    }
                                                                
    /** 计算sdcard上的剩余空间 **/
    private int freeSpaceOnSd() {
        StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
        double sdFreeMB = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB;
        return (int) sdFreeMB;
    } 
                                                                
    /** 将url转成文件名 **/
    private String convertUrlToFileName(String url) {
        String[] strs = url.split("/");
        return strs[strs.length - 1] + WHOLESALE_CONV;
    }
                                                                
    /** 获得缓存目录 **/
    private String getDirectory() {
        String dir = getSDPath() + "/" + CACHDIR;
        return dir;
    }
                                                                
    /** 取SD卡路径 **/
    private String getSDPath() {
        File sdDir = null;
        boolean sdCardExist = Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED);  //判断sd卡是否存在
        if (sdCardExist) {
            sdDir = Environment.getExternalStorageDirectory();  //获取根目录
        }
        if (sdDir != null) {
            return sdDir.toString();
        } else {
            return "";
        }
    } 
                                                            
    /**
     * 根据文件的最后修改时间进行排序
     */
    private class FileLastModifSort implements Comparator<File> {
        public int compare(File arg0, File arg1) {
            if (arg0.lastModified() > arg1.lastModified()) {
                return 1;
            } else if (arg0.lastModified() == arg1.lastModified()) {
                return 0;
            } else {
                return -1;
            }
        }
    }
}

 4)ImageGetFromHttp.java

  

 

 

package com.yitu.Util;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
/**
 * http://keegan-lee.diandian.com/post/2012-12-06/40047548955
 * @author wsf
 *
 */
public class ImageGetFromHttp {
private  Bitmap result=null;                            
    private static final String LOG_TAG = "ImageGetFromHttp";    
    public  Bitmap downloadBitmap(String url,Context context) 
    {
        /**
        * 此处为wsf添加代码 
        */
       
        AnsyImageLoad imageload=new AnsyImageLoad(url,
        new doCallback() {
@Override
public void doPostBack(Bitmap bitmap) {
// TODO Auto-generated method stub
Log.i("net", "被执行了一次--->docallback");
result = bitmap;
}
},context);
        imageload.execute(url);
        /**
        * 以上为wsf添加代码 
        */
        return result;
    }
                                                       
    /*
     * An InputStream that skips the exact number of bytes provided, unless it reaches EOF.
     */
    static class FlushedInputStream extends FilterInputStream {
        public FlushedInputStream(InputStream inputStream) {
            super(inputStream);
        }
                                                       
        @Override
        public long skip(long n) throws IOException {
            long totalBytesSkipped = 0L;
            while (totalBytesSkipped < n) {
                long bytesSkipped = in.skip(n - totalBytesSkipped);
                if (bytesSkipped == 0L) {
                    int b = read();
                    if (b < 0) {
                        break;  // we reached EOF
                    } else {
                        bytesSkipped = 1; // we read one byte
                    }
                }
                totalBytesSkipped += bytesSkipped;
            }
            return totalBytesSkipped;
        }
    }
    public interface doCallback
    {
    /**
    * 回调传输下载 下来后的值
    * @param bitmap
    */
    void doPostBack(Bitmap bitmap);
    }
    
}


6)自定义的控件 myImageView

 

package com.df.widget;//com.df.widget.myImageView
import com.yitu.Util.BitmapCache;
import com.yitu.Util.ImageGetFromHttp.doCallback;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;
/**
 * 自定义图像显示控件
 * (所使用到的类有三个,AsyImageLoad.java,BitmapCache.java,ImageFileCache.java,ImageGetFromHttp.java
 * ImageMemoryCache.java)
 * @author wsf
 *
 */
public class myImageView extends ImageView {
private Context mycontext;
public myImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
this.mycontext=context;
}
public myImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
this.mycontext=context;
}
public myImageView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
this.mycontext=context;
}
/**
* 采集远程的网络数据
* @param url
*/
public void setImage(String url)
{
BitmapCache bitcatch=new BitmapCache();
bitcatch.setBitmap(url, 
mycontext,new doCallback() {
public void doPostBack(Bitmap bitmap) {
// TODO Auto-generated method stub
BitmapDrawable drawable=new BitmapDrawable(bitmap);
myImageView.this.setBackgroundDrawable(drawable);
}
});
}
/**
* 根所本地的资源来设定图片的背景资源
* @param resid
*/
public void setImage(int resid)
{
this.setBackgroundResource(resid);
}
}

 

7)调用示例

  /**使用自定义的图片显示控件*/

myimageview=(myImageView)findViewById(R.id.my_view);
myimageview.setImage("http://d.hiphotos.baidu.com/album/w%3D2048/sign=79c90f23728da9774e2f812b8469f919/8b13632762d0f703a2d659cc09fa513d2697c5be.jpg");
/**使用自定义的图片显示控件*/

 

 8)layout.中的布局文件

 

     <com.df.widget.myImageView 

        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/my_view"        
        />

 

 

android 图片异步下载 缓存处理 自定义ImageView_第1张图片 

9)最后效果

 

 

 

    

 android 图片异步下载 缓存处理 自定义ImageView_第2张图片

 

 

你可能感兴趣的:(imageview)