生成缓存文件
//读取服务器返回的流里的数据,把数据写到本地文件,缓存起来
//写到哪里看需要,可以写到sd卡,也可以写到内部缓存文件夹,此处为写到内部缓存文件夹
//缓存文件名一般为本身的文件名,可以用截取的方式把它扣出来
File file = new File(getCacheDir(),getFileName(path));
//文件输出流
FileOutputStream fos = new FileOutputStream(file);
byte[] b = new byte[1024]; //每次读取1k
int len = 0;
while((len = is.read(b)) != -1){
fos.write(b, 0, len); //写到缓存文件里
}
fos.close();
此后直接从文件路径读取数据
//bitmap表示图片,读取出流里的数据,并构造成位图对象
//流里已经没有数据了,就不能够从流里读了
// Bitmap bm = BitmapFactory.decodeStream(is);
//直接拿file的绝对路径
Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
如此,每次加载图片时虽然是从网上下载之后存在缓存里,但是每次还是从网上下,因此需要判断一下是否存在该文件的缓存数据,如果有直接从缓存里读
public void click(View v){
//下载图片
//1,确定网址
final String path = "http://pic15.nipic.com/20110630/6322714_105550198325_2.jpg";
//缓存文件名一般为本身的文件名,可以用截取的方式把它扣出来
final File file = new File(getCacheDir(),getFileName(path));
//判断缓存中是否存在该文件
if(file.exists()){
//如果缓存在,从缓存读取文件
Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
//直接在主线程中运行,就不用多此一举的发消息了
iv.setImageBitmap(bm);
}
else{
//如果缓存不存在,从网络下载
Thread t = new Thread(){
@Override
public void run() {
try {
//2,把网址封装成一个url对象
URL url = new URL(path);
//3,获取连接对象,客户端与网址建立连接的连接对象,此时还没有建立连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//4,对连接对象进行初始化
//设置请求方法,注意大写
conn.setRequestMethod("GET");
//设置连接超时,5s没响应
conn.setConnectTimeout(5000);
//设置读取超时(有响应,但5s没有把数据传给你)
conn.setReadTimeout(5000);
//5,发送请求,与服务器建立连接
conn.connect();
//如果响应码为200,说明请求成功
if(conn.getResponseCode() == 200){
//获取服务器响应头中的流,流里的数据就是客户端请求的数据
InputStream is = conn.getInputStream();
//读取服务器返回的流里的数据,把数据写到本地文件,缓存起来
//写到哪里看需要,可以写到sd卡,也可以写到内部缓存文件夹,此处为写到内部缓存文件夹
//文件输出流
FileOutputStream fos = new FileOutputStream(file);
byte[] b = new byte[1024]; //每次读取1k
int len = 0;
while((len = is.read(b)) != -1){
fos.write(b, 0, len); //写到缓存文件里
}
fos.close();
//bitmap表示图片,读取出流里的数据,并构造成位图对象
//流里已经没有数据了,就不能够从流里读了
// Bitmap bm = BitmapFactory.decodeStream(is);
//直接拿file的绝对路径
Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
//创建消息对象
// Message msg = new Message(); //最好不要直接去new,可以节省内存
Message msg = handler.obtainMessage();
//1为成功
msg.what = 1;
//消息对象可以携带数据
msg.obj = bm;
//把消息发送致主线程的消息队列
handler.sendMessage(msg);
}
else {
//开发中还要通过具体的响应码去判断是哪一种
// Toast.makeText(MainActivity.this, "请求失败", 0).show();
Message msg = handler.obtainMessage();
//0为失败
msg.what = 0;
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
t.start();
}
}
//截取文件名
public String getFileName(String path){
//拿到最后一个"/"的索引值
int index = path.lastIndexOf("/");
return path.substring(index + 1); //如果不加1,截取的是"/文件名"
}
以上为下载图片的核心代码,在实际开发中还需要考虑很多细节性的问题,比如3G下载到一半转wifi,wifi下载一半断网,下载时有同名文件夹,一个图片下载10min下不下来怎么处理,等等,但核心代码就是以上,其它还要根据具体情况具体分析