麦洛开通博客以来,有一段时间没有更新博文了.主要是麦洛这段时间因项目开发实在太忙了.今天周六还在公司加班,苦逼程序猿都是这样生活的.

今天在做项目的时候,有一个实现异步加载图片的功能,虽然比较简单但还是记录一下吧.因为麦洛之前实现异步加载图片都是使用了AsynTask这个API,继续这个类,实现起来非常简单也很方便.在doInBackground()方法里实现下载逻辑.具体实现如下
实现逻辑是:先从内存中读取,如果内存中有这张图片,则直接使用;如果内存没有再到sdcard上读取,如果有则显示;如果sdcard上还没有则到网络上读取.内存中开启缓存是参考了网上的实现.麦洛在这里非常感谢喜欢分享的程序猿们.
public class ImageDownloader extends AsyncTask<String, Integer, Object> {
private static final String TAG = "ImageDownloader";
// 为了加快速度,在内存中开启缓存(主要应用于重复图片较多时,或者同一个图片要多次被访问,比如在ListView时来回滚动)
private Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
/**
* 显示图片的控件
*/
private ImageView mImageView;
public ImageDownloader(ImageView image) {
mImageView = image;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Object doInBackground(String... params) {
// Log.i("ImageDownloader", "loading image...");
String url = params[0];
Drawable drawable = null;
try {
if (!"".equals(url) && url != null) {
String fileName = url.hashCode()+".jpg";
// 如果缓存过就从缓存中取出数据
if (imageCache.containsKey(fileName)) {
SoftReference<Drawable> softReference = imageCache.get(fileName);
drawable = softReference.get();
if (drawable != null) {
return drawable;
}
}
File dir = new File(FileConstant.IMAGE_FILE_PATH);
if (!dir.exists()) {
boolean m = dir.mkdirs();
}
File file = new File(dir, fileName);
if (file.exists() && file.length() > 0) {
Log.i(TAG, "load image from sd card");
// 如果文件存在则直接读取sdcard
drawable = readFromSdcard(file);
} else {
//file.createNewFile();
Log.i(TAG, "load image from network");
URL imageUrl = new URL(url);
// 写入sdcard
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
saveImageFile(imageUrl, file);
drawable = Drawable.createFromStream(new FileInputStream(file), fileName);
}else{
//直接从流读取
drawable = Drawable.createFromStream(imageUrl.openStream(), fileName);
}
}
if(drawable!=null){
//保存在缓存中
imageCache.put(fileName, new SoftReference<Drawable>(drawable));
}
}
} catch (Exception e) {
e.printStackTrace();
}
return drawable;
}
/**
* save image
*/
private void saveImageFile(URL url, File file) {
FileOutputStream out = null;
InputStream in = null;
try {
file.deleteOnExit();
out = new FileOutputStream(file);
in = url.openStream();
byte[] buf = new byte[1024];
int len = -1;
while((len = in.read(buf))!=-1){
out.write(buf, 0, len);
out.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 从sdcard中获取图片
*/
private Drawable readFromSdcard(File file) throws Exception {
FileInputStream in = new FileInputStream(file);
return Drawable.createFromStream(in, file.getName());
}
@Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
Drawable drawable = (Drawable) result;
if (mImageView != null && drawable != null) {
mImageView.setBackgroundDrawable(drawable);
}
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected void onCancelled() {
super.onCancelled();
}
}
使用时:
ImageDownloader loader = new ImageDownloader(imageView); loader.execute(url);
其实这样的话,还有一些隐患的,就是说这个类实现还是有些问题的.比如每次都在imageView中设置网络上的图片时,其实是没有使用到这个类里面的内存缓存的,就是imageCache
Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
因为每次设置imageView的时候,都是new了一个ImageDownloader的对象.所以每个ImageDownloader对象里面都是独立的一个imageCache.
另外,AsynTask也是一个线程.而每次使用都开一个线程来load 图片,对线程个数没有进行显示,毕竟线程数目还是有限制的.
所以麦洛今天发现了这个问题,于是参考了别人的实现,使用了线程池,实现逻辑也上面的代码一样,先从内存读取,如果没有到sdcard读取,如果还是没有,则是网络读取;实现没有使用AsynTask,具体代码如下:
/**
* 异步加载图片,并将图片设置到ImageView控件中
*/
public class ImageDownloader extends AsyncTask<String, Integer, Object> {
private static final String TAG = "ImageDownloader";
// 为了加快速度,在内存中开启缓存(主要应用于重复图片较多时,或者同一个图片要多次被访问,比如在ListView时来回滚动)
private Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
/**
* 显示图片的控件
*/
private ImageView mImageView;
public ImageDownloader(ImageView image) {
mImageView = image;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Object doInBackground(String... params) {
// Log.i("ImageDownloader", "loading image...");
String url = params[0];
Drawable drawable = null;
try {
if (!"".equals(url) && url != null) {
String fileName = url.hashCode()+".jpg";
// 如果缓存过就从缓存中取出数据
if (imageCache.containsKey(fileName)) {
SoftReference<Drawable> softReference = imageCache.get(fileName);
drawable = softReference.get();
if (drawable != null) {
return drawable;
}
}
File dir = new File(FileConstant.IMAGE_FILE_PATH);
if (!dir.exists()) {
boolean m = dir.mkdirs();
}
File file = new File(dir, fileName);
if (file.exists() && file.length() > 0) {
Log.i(TAG, "load image from sd card");
// 如果文件存在则直接读取sdcard
drawable = readFromSdcard(file);
} else {
//file.createNewFile();
Log.i(TAG, "load image from network");
URL imageUrl = new URL(url);
// 写入sdcard
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
saveImageFile(imageUrl, file);
drawable = Drawable.createFromStream(new FileInputStream(file), fileName);
}else{
//直接从流读取
drawable = Drawable.createFromStream(imageUrl.openStream(), fileName);
}
}
if(drawable!=null){
//保存在缓存中
imageCache.put(fileName, new SoftReference<Drawable>(drawable));
}
}
} catch (Exception e) {
e.printStackTrace();
}
return drawable;
}
/**
* save image
*/
private void saveImageFile(URL url, File file) {
FileOutputStream out = null;
InputStream in = null;
try {
file.deleteOnExit();
out = new FileOutputStream(file);
in = url.openStream();
byte[] buf = new byte[1024];
int len = -1;
while((len = in.read(buf))!=-1){
out.write(buf, 0, len);
out.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 从sdcard中获取图片
*/
private Drawable readFromSdcard(File file) throws Exception {
FileInputStream in = new FileInputStream(file);
return Drawable.createFromStream(in, file.getName());
}
@Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
Drawable drawable = (Drawable) result;
if (mImageView != null && drawable != null) {
mImageView.setBackgroundDrawable(drawable);
}
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected void onCancelled() {
super.onCancelled();
}
}
这个ImageDownloader2的使用也很简单
public class ImageUtil {
/**
* image loader
*/
static ImageDownloader2 loader = null;
/**
* load image
*/
public static void loadImage(String url,final ImageView imageView){
if(loader == null){
loader = new ImageDownloader2();
}
loader.loadDrawable(url, new ImageCallback() {
@Override
public void imageLoaded(Drawable imageDrawable) {
if(imageDrawable!=null){
imageView.setBackgroundDrawable(imageDrawable);
}
}
});
}
}
每次在使用是需要调用ImageUtil.loadImage(url,imageView)将图片url已经需要显示图片的控件ImageView的引用传入就可以了.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Android异步加载图片
# Android异步加载
# Android加载图片
# Android使用AsyncTask加载图片的操作流程
# Android实现网络加载图片点击大图后浏览可缩放
# android中Glide实现加载图片保存至本地并加载回调监听
# Android中Glide加载图片并实现图片缓存
# Android不压缩图片实现高清加载巨图实例
# 都是
# 也很
# 加载
# 要多
# 应用于
# 如在
# 使用了
# 在这里
# 都在
# 还在
# 则是
# 中有
# 这个问题
# 这段
# 这张
# 并将
# 如果没有
# 实在太
# 再到
# 还有一些
相关文章:
实惠建站价格推荐:2025年高性价比自助建站套餐解析
网站制作企业,网站的banner和导航栏是指什么?
韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐
如何制作算命网站,怎么注册算命网站?
微信小程序 五星评分(包括半颗星评分)实例代码
如何用腾讯建站主机快速创建免费网站?
网站建设制作需要多少钱费用,自己做一个网站要多少钱,模板一般多少钱?
如何在阿里云通过域名搭建网站?
C++中引用和指针有什么区别?(代码说明)
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
建站之星图片链接生成指南:自助建站与智能设计教程
我的世界制作壁纸网站下载,手机怎么换我的世界壁纸?
如何确认建站备案号应放置的具体位置?
标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?
如何正确选择百度移动适配建站域名?
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
如何快速搭建虚拟主机网站?新手必看指南
建站之星价格显示格式升级,你的预算足够吗?
如何在Ubuntu系统下快速搭建WordPress个人网站?
自助网站制作软件,个人如何自助建网站?
如何解决VPS建站LNMP环境配置常见问题?
C++如何将C风格字符串(char*)转换为std::string?(代码示例)
宝塔Windows建站如何避免显示默认IIS页面?
建站中国必看指南:CMS建站系统+手机网站搭建核心技巧解析
一键网站制作软件,义乌购一件代发流程?
网站制作员失业,怎样查看自己网站的注册者?
湖南网站制作公司,湖南上善若水科技有限公司做什么的?
新网站制作渠道有哪些,跪求一个无线渠道比较强的小说网站,我要发表小说?
沈阳制作网站公司排名,沈阳装饰协会官方网站?
如何在Mac上搭建Golang开发环境_使用Homebrew安装和管理Go版本
番禺网站制作公司哪家值得合作,番禺图书馆新馆开放了吗?
武汉网站如何制作,黄黄高铁武穴北站途经哪些村庄?
jQuery 常见小例汇总
如何通过.red域名打造高辨识度品牌网站?
ui设计制作网站有哪些,手机UI设计网址吗?
如何通过云梦建站系统实现SEO快速优化?
建站主机服务器选购指南:轻量应用与VPS配置解析
高防服务器租用如何选择配置与防御等级?
公司网站制作费用多少,为公司建立一个网站需要哪些费用?
建站之星官网登录失败?如何快速解决?
mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?
如何自定义建站之星网站的导航菜单样式?
广州建站公司哪家好?十大优质服务商推荐
专业网站设计制作公司,如何制作一个企业网站,建设网站的基本步骤有哪些?
建站之星免费版是否永久可用?
建站之星安全性能如何?防护体系能否抵御黑客入侵?
电商网站制作公司有哪些,1688网是什么意思?
宝塔建站教程:一键部署配置流程与SEO优化实战指南
开源网站制作软件,开源网站什么意思?
网站视频制作书签怎么做,ie浏览器怎么将网站固定在书签工具栏?
*请认真填写需求信息,我们会在24小时内与您取得联系。