Android 异步加载网络图片并缓存到本地 软引用 学习分享

哥特帝景 2014-03-04 02:32:24
加精
在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片。

软引用是一个现在非常流行的方法,用户体验比较好,不用每次都需要从网络下载图片,如果下载后就存到本地,下次读取时首先查看本地有没有,如果没有再从网络读取。

记得2月份在和爱奇艺公司的项目总监一起搞联通的OTT盒子的时候他就提了一下软引用,奇艺做的手机客户端就是采用这种方法,所以你会发现奇艺客户端占用很大的空间,下面就分享一下异步加载网络图片的方法吧。

FileCache.java

[java] view plaincopy

import java.io.File;
import android.content.Context;

public class FileCache {

private File cacheDir;

public FileCache(Context context) {
// 找一个用来缓存图片的路径
if (android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED))
cacheDir = new File(android.os.Environment.getExternalStorageDirectory(),
"文件夹名称");
else
cacheDir = context.getCacheDir();
if (!cacheDir.exists())
cacheDir.mkdirs();
}

public File getFile(String url) {
String filename = String.valueOf(url.hashCode());
File f = new File(cacheDir, filename);
return f;
}

public void clear() {
File[] files = cacheDir.listFiles();
if (files == null)
return;
for (File f : files)
f.delete();
}

}




HttpUtil.java



[java] view plaincopy

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;

/**
* Http 请求工具类
*
* @author Scorpio.Liu
*
*/
public class HttpUtil {

/**
* 获取响应字符串
*
* @param path
* 路径
* @param parameters
* 参数
* @return 响应字符串
*/
public static String getResponseStr(String path, Map<String, String> parameters) {
StringBuffer buffer = new StringBuffer();
URL url;
try {
if (parameters != null && !parameters.isEmpty()) {
for (Map.Entry<String, String> entry : parameters.entrySet()) {
// 完成转码操作
buffer.append(entry.getKey()).append("=")
.append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("&");
}
buffer.deleteCharAt(buffer.length() - 1);
}
url = new URL(path);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(3000);
urlConnection.setRequestMethod("POST");
urlConnection.setDoInput(true);// 表示从服务器获取数据
urlConnection.setDoOutput(true);// 表示向服务器写数据
// 获得上传信息的字节大小以及长度
byte[] mydata = buffer.toString().getBytes();
// 表示设置请求体的类型是文本类型
urlConnection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
urlConnection.setRequestProperty("Content-Length", String.valueOf(mydata.length));
// 获得输出流,向服务器输出数据
OutputStream outputStream = urlConnection.getOutputStream();
outputStream.write(mydata, 0, mydata.length);
outputStream.close();
int responseCode = urlConnection.getResponseCode();
if (responseCode == 200) {
return changeInputStream(urlConnection.getInputStream());
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

private static String changeInputStream(InputStream inputStream) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int len = 0;
String result = "";
if (inputStream != null) {
try {
while ((len = inputStream.read(data)) != -1) {
outputStream.write(data, 0, len);
}
result = new String(outputStream.toByteArray(), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}

public static InputStream getInputStream(String path) {
URL url;
try {
url = new URL(path);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(3000);
urlConnection.setRequestMethod("GET");
urlConnection.setDoInput(true);// 表示从服务器获取数据
urlConnection.connect();
if (urlConnection.getResponseCode() == 200)
return urlConnection.getInputStream();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}

public static byte[] readStream(InputStream inStream) throws Exception {
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);

}
outSteam.close();
inStream.close();
return outSteam.toByteArray();
}

public static void CopyStream(String url, File f) {
FileOutputStream fileOutputStream = null;
InputStream inputStream = null;
try {
inputStream = getInputStream(url);
byte[] data = new byte[1024];
int len = 0;
fileOutputStream = new FileOutputStream(f);
while ((len = inputStream.read(data)) != -1) {
fileOutputStream.write(data, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

}


请点击这个链接阅读详细介绍:http://g.csdn.net/5265982
...全文
8859 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
changzhengcome 2016-07-11
  • 打赏
  • 举报
回复
package changzheng.musicv4.entil; import java.io.File; import java.io.InputStream; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import changzheng.musicv4.R; import changzheng.musicv4.util.HttpUtils; import android.content.Context; import android.graphics.Bitmap; import android.os.Handler; import android.os.Message; import android.widget.ImageView; import android.widget.ListView; /** * 异步批量加载图片的工具类 */ public class ImageLoader { private HashMap<String, SoftReference<Bitmap>> cache = new HashMap<String, SoftReference<Bitmap>>(); private Context context; private List<ImageLoadTask> tasks = new ArrayList<ImageLoadTask>(); private Thread workThread; private boolean isLoop = true; private ListView listView; private Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { switch (msg.what) { case HANDLER_IMAGE_LOAD_SUCCESS: //给相应的ImageView设置Bitmap ImageLoadTask task = (ImageLoadTask) msg.obj; Bitmap bitmap = task.bitmap; ImageView imageView = (ImageView) listView.findViewWithTag(task.path); if(imageView != null){ if(bitmap!=null){ imageView.setImageBitmap(bitmap); }else{ imageView.setImageResource(R.drawable.ic_launcher); } } break; } } }; public static final int HANDLER_IMAGE_LOAD_SUCCESS = 1; public ImageLoader(Context context, ListView listView) { this.listView = listView; this.context = context; //启动工作线程 轮循任务集合 workThread = new Thread(){ public void run() { while(isLoop){ if(!tasks.isEmpty()){ //不是空集 ImageLoadTask task = tasks.remove(0); String url = task.path; //发送http请求 下载图片 Bitmap bitmap = loadBitmap(url); task.bitmap = bitmap; //更新界面 发消息给handler Message msg = new Message(); msg.what = HANDLER_IMAGE_LOAD_SUCCESS; msg.obj = task; handler.sendMessage(msg); }else{ //空集合 等待 try { synchronized (workThread) { workThread.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } } } } }; workThread.start(); } /** * 通过url地址 发送http请求 获取图片 * @param url * @return */ public Bitmap loadBitmap(String url){ try { InputStream is = HttpUtils.getInputStream(url); //解析Bitmap 执行压缩算法 获取合适尺寸的图片 Bitmap bitmap = BitmapUtils.loadBitmap(is, 50, 50); //把bitmap存入内存缓存 cache.put(url, new SoftReference<Bitmap>(bitmap)); //把bitmap存入文件中 String filename = url.substring(url.lastIndexOf("/")+1); File file = new File(context.getCacheDir(), "images/"+filename); BitmapUtils.save(bitmap, file); return bitmap; } catch (Exception e) { e.printStackTrace(); } return null; } public void displayImage(String url, ImageView imageView){ //给ivPic设置图片 //先去内存缓存中查询 看有没有 SoftReference<Bitmap> ref=cache.get(url); if(ref!=null){ //以前存过 Bitmap bitmap = ref.get(); if(bitmap!=null) { //以前存的还没有被干掉 imageView.setImageBitmap(bitmap); return; } } //去文件缓存中读取 String filename = url.substring(url.lastIndexOf("/")+1); File file = new File(context.getCacheDir(), "images/"+filename); Bitmap bitmap = BitmapUtils.loadBitmap(file); if(bitmap!=null){ //一旦从文件中读取出来 先存入内存缓存 cache.put(url, new SoftReference<Bitmap>(bitmap)); imageView.setImageBitmap(bitmap); return; } // new Thread(){}.start(); 不能写 写了会卡 //向任务集合中添加一个图片下载任务 imageView.setTag(url); ImageLoadTask task = new ImageLoadTask(); task.path = url; tasks.add(task); synchronized (workThread) { //唤醒工作线程 起来干活 workThread.notify(); } } class ImageLoadTask { String path; //保存图片下载路径 Bitmap bitmap; //下载成功后的图片 } public void stopThread() { isLoop = false; synchronized (workThread) { workThread.notify(); } } }
IT_Transformers 2014-12-21
  • 打赏
  • 举报
回复
就现在Android版本的升级以后,貌似不推荐使用软引用了,应该是他的回收机制有所改变了已经
austin9972 2014-03-15
  • 打赏
  • 举报
回复
谢谢楼主分享
nj_dobetter 2014-03-12
  • 打赏
  • 举报
回复
强大!~~~~~~~~~~~~~~~~~~~~~
ameyume 2014-03-11
  • 打赏
  • 举报
回复
使用方法:
		mImg = (ImageView)findViewById(R.id.img);
		
		mImgLoader = new ImageLoader(this, true);
		mImgLoader.DisplayImage("http://img.my.csdn.net/uploads/201312/02/1385997812_2547.jpg", mImg);
如果图片太大还可以调用decodeFile进行缩减大图。 增加权限:
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
jiaoyan101 2014-03-10
  • 打赏
  • 举报
回复
qiutai2008 2014-03-09
  • 打赏
  • 举报
回复
楼主高人也啊,支持一下下
my03131302 2014-03-08
  • 打赏
  • 举报
回复
阿亮7012 2014-03-07
  • 打赏
  • 举报
回复
olyhome 2014-03-06
  • 打赏
  • 举报
回复
可用,,能实现吗???
qiutai2008 2014-03-05
  • 打赏
  • 举报
回复
支持一下,谢谢楼主分享,我正需要这个呢。
ftjavayp 2014-03-05
  • 打赏
  • 举报
回复
hugh_z 2014-03-05
  • 打赏
  • 举报
回复
learning
kiss_1988 2014-03-05
  • 打赏
  • 举报
回复
小裴同学 2014-03-05
  • 打赏
  • 举报
回复
都烂大街了你还来分享。。。。
风子参上 2014-03-05
  • 打赏
  • 举报
回复
4.0版本后软引用基本废了,用LRU和DISKLRU吧
sunzhurong 2014-03-04
  • 打赏
  • 举报
回复
支持一下,用上了。
line_us 2014-03-04
  • 打赏
  • 举报
回复
引用 4 楼 u013908685 的回复:
份在和爱奇艺公司的项目总监一起搞联通的。
  • 打赏
  • 举报
回复
得2月份在和爱奇艺公司的项目总监一起搞联通的OTT盒子的时候他就提了一下软引用,奇艺做的手机客户端就是采用这种方法,所以你会发现奇艺客户端占用很大的空间
ameyume 2014-03-04
  • 打赏
  • 举报
回复
支持下
加载更多回复(4)

566

社区成员

发帖
与我相关
我的任务
社区描述
英特尔® 边缘计算,聚焦于边缘计算、AI、IoT等领域,为开发者提供丰富的开发资源、创新技术、解决方案与行业活动。
社区管理员
  • 英特尔技术社区
  • shere_lin
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧