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"
/>
9)最后效果