网络图片异步加载 其实有关图片加载存在这样一个问题,图片的下载始终是一个耗时的操作,这个时候如果把图片加载放在主线程中话的是不明智的,模拟一个这样的场景, 假如在一个listview或RecyclerView中,每一个listitem中都有一张网络图片,假如不使用网络异步处理的话,滑动工作会特别卡,因为必须加载网图片后 ,才会加载下个item。除了这些,网络图片加载还存在很多优化,下面是ImageLoader对于网络图片加载的优化内容:

  • 加载过程使用异步,这里使用AsyncTask
  • 加载图片后,将图片放入缓存,不必每次都从网络上请求,节省流量,加快加载速度
  • 使用ViewHolder,这点就不必多说了
  • 监听滑动过程,其实我们知道的,在滑动的时候其实我们是没有必要加载图片的,等滑动结束的时候,加载当前页面的图片

  其实网上有很多类似的开源框架,但是为了理解其中原理,我自己写了一个ImageLoader。同时在加载过程中我自己写了一个ProgressDialog,显示效果如下

  1、关于异步加载:

  我的Demo里面使用的异步加载方法是AsyncTask,AsyncTask是一个很创建的异步方式,这里就不做太多介绍,只要在doInBackground方法中添加图片的网络加载即可,以下是代码:

private class NewSAsyncTask extends AsyncTask<String, Void, Bitmap> {
private ImageView mimageView;
private String mUrl;
private int mType; public NewSAsyncTask(ImageView imageview, String url,int type) {
mimageView = imageview;
mUrl = url;
mType=type; } @Override
protected Bitmap doInBackground(String... params) {
String url=params[0];
Bitmap bitmap=getBitmapFromUrl(mUrl,mType);
if(bitmap!=null){
addBitmapToCache(url, bitmap);
}
return bitmap;
} @Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if (mimageView.getTag().equals(mUrl)) {
mimageView.setImageBitmap(bitmap);
} } }

  2、加载的图片放入缓存,或从缓存中读取图片--LruCache

  LruCache是android提供给我的一个有关于手机缓存中插入和读取数据的类,使用起来也很方便,以下是代码:

public ImageLoaderUtil() {
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 8;
mcache = new LruCache<String, Bitmap>(cacheSize) {
@SuppressLint("NewApi")
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
} public void addBitmapToCache(String url, Bitmap bitmap) {
if (getBitmapFromCache(url) == null) {
mcache.put(url, bitmap);
}
} public Bitmap getBitmapFromCache(String url) {
return mcache.get(url); }

  上面的代码中先是获取当前手机可用的最大内容,然后取其8分之一,用于我们使用的缓存。

  3、判断手指滑动状态

  这个很简单,直接使用ListView或RecyclerView的滑动监听即可。当手指停止滑动的时候,判断当前屏幕中都显示哪些item,然后在加载这些item。这样一来,在手指滑动的过程中,不进行任何有关加载的相关操作,节省了流量,加快了加载速度,同时提升了用户体验。

  4、ImageLoader的逻辑顺序

  首先判断在LruCache中通过url判断是否有欲加载的图片,没有的话从网络上加载,并使用url和图片的键值对放入LruCache中。同时监听手机滑动,当收停止滑动的时候在进行加载,滑动过程中不进行任何加载。

  下面是ImageLoader的完整代码:

package xml.org.today.util;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL; import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.widget.ImageView; public class ImageLoaderUtil {
private LruCache<String, Bitmap> mcache; public ImageLoaderUtil() {
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 8;
mcache = new LruCache<String, Bitmap>(cacheSize) {
@SuppressLint("NewApi")
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
} public void addBitmapToCache(String url, Bitmap bitmap) {
if (getBitmapFromCache(url) == null) {
mcache.put(url, bitmap);
}
} public Bitmap getBitmapFromCache(String url) {
return mcache.get(url); } /**
* 异步加载网络图片
*
* @param imageview
* @param url
* @param type 1、圆角图片
*/
public void getImageByAsyncTask(ImageView imageview, String url, int type) {
Bitmap bitmap = getBitmapFromCache(url);
if (bitmap == null) {
new NewSAsyncTask(imageview, url, type).execute(url);
} else {
imageview.setImageBitmap(bitmap);
} } private class NewSAsyncTask extends AsyncTask<String, Void, Bitmap> {
private ImageView mimageView;
private String mUrl;
private int mType; public NewSAsyncTask(ImageView imageview, String url, int type) {
mimageView = imageview;
mUrl = url;
mType = type; } @Override
protected Bitmap doInBackground(String... params) {
String url = params[0];
Bitmap bitmap = getBitmapFromUrl(mUrl, mType);
if (bitmap != null) {
addBitmapToCache(url, bitmap);
}
return bitmap;
} @Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if (mimageView.getTag().equals(mUrl)) {
mimageView.setImageBitmap(bitmap);
} } } public Bitmap getBitmapFromUrl(String urlString, int type) {
Bitmap bitmap;
Bitmap outbitmap;
InputStream is = null;
try {
URL url = new URL(urlString);
try {
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
is = new BufferedInputStream(connection.getInputStream());
bitmap = BitmapFactory.decodeStream(is);
if (type == 1) {
outbitmap = toRoundBitmap(bitmap);
} else {
outbitmap = bitmap;
} connection.disconnect();
return outbitmap;
} catch (IOException e) {
e.printStackTrace();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
} public static Bitmap toRoundBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
Paint paint = new Paint();
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Rect rect;
if (width >= height) {
rect = new Rect((width - height) / 2, 0, (width - height) / 2
+ height, height);
} else {
rect = new Rect(0, (height - width) / 2, width, width
+ (height - width) / 2);
}
RectF rectF = new RectF(rect);
canvas.drawOval(rectF, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rectF, paint);
return output;
}
}

  调用的方式也很简单:

ImageLoaderUtil mImageLoaderUtil=new ImageLoaderUtil();
mImageLoaderUtil.getImageByAsyncTask(mView,mUrl,1);

  上面的代码中mView是欲加载图片的ImageView,mUrl是图片的远程地址,1代表欲加载圆角图片。

  上面代码的github地址是:https://github.com/jiushi555/ImageLoaderDemo。

关于ImageLoader的一些东西的更多相关文章

  1. android使用ImageLoader实现图片缓存(安卓开发必备)

    相信大家在学习以及实际开发中基本都会与网络数据打交道,而这其中一个非常影响用户体验的就是图片的缓存了,若是没有弄好图片缓存,用户体验会大大下降,总会出现卡顿情况,而这个问题尤其容易出现在ListVie ...

  2. ImageLoader图片加载

    http://blog.csdn.net/liu1164316159/article/details/38728259       转载请注明http://write.blog.csdn.net/po ...

  3. 【jar包】图片的异步加载--【 Imageloader】

    Android Imageloader图片异步加载 Imageloader是一个在android平台下简单的下载.显示.缓存空间的图片加载库. 异步下载网络图片并可以在UI线程更新View,使用二级缓 ...

  4. 关于 ImageLoader 说的够细了。。。

    简介ImageLoader(一) 分类: android 开源及第三方项目2014-05-30 12:14 14126人阅读 评论(0) 收藏 举报 ImageLoader 使用该开源项目的之前,先给 ...

  5. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  6. iOS有关横向TableView的东西

    之前看到Apple store里面有横向的tableview,当然也有可能是collectionview啦. 尤其是项目中只有一条那么需要横向滑动的东西,就没有必要使用庞大的collectionvie ...

  7. 使用ENode框架前您需要了解的东西(初稿)

    选择ENode意味着什么可能很多人还不太清楚.我简单整理了一下: 意味着你选择了:你需要做DDD领域建模.选择了事件驱动的架构.选择了CQRS架构.选择了最终一致性.选择了事件溯源.选择了分布式.这些 ...

  8. android ImageLoader 混淆加载drawable出现黑色图片的解决方案

    在网上找了很久,没有找到.后来看了源码才知道... 多线程异步加载和显示图片(图片来源于网络.sd卡.assets文件夹,drawable文件夹(不能加载9patch),新增加载视频缩略图) Stri ...

  9. 如何写出高质量的技术博客 这边文章出自http://www.jianshu.com/p/ae9ab21a5730 觉得不错直接拿过来了 好东西要大家分享嘛

        如何写出高质量的技术博客?答案是:如果你想,就一定能写出高质量的技术博客.看起来很唯心,但这就是事实.有足够愿力去做一件目标明确,有良好反馈系统的事情往往很简单.就是不停地训练,慢慢地,你自己 ...

随机推荐

  1. Linux下Nano命令使用指南

    1.什么时候用nano? 一般网络很卡,ssh时一用vim/vi 就死窗口,或者死机的情况 2.如何使用?   打开或新建文件 #nano 文件名    禁用自动换行 #nano -w /etc/fs ...

  2. H5案例分享:移动端滑屏 touch事件

    移动端滑屏 touch事件 移动端触屏滑动的效果的效果在电子设备上已经被应用的越来越广泛,类似于PC端的图片轮播,但是在移动设备上,要实现这种轮播的效果,就需要用到核心的touch事件.处理touch ...

  3. dedecms 列表页 list 判断flag给定指定样式 (本地测试有效)

    {dede:list pagesize='10'} [field:array runphp='yes'] if (@me['flag']=='a') @me=' <a class="n ...

  4. ural 1303 Minimal Coverage(贪心)

    链接: http://acm.timus.ru/problem.aspx?space=1&num=1303 按照贪心的思想,每次找到覆盖要求区间左端点时,右端点最大的线段,然后把要求覆盖的区间 ...

  5. 【Stirling Number】

    两类Stirling Number的简介与区别(参考自ACdreamer的CSDN) Stirling Number I --- s(n,k):将n个物体排成k个非空循环排列(环)的方法数. 递推式: ...

  6. knockout.js-创建视图模型

    监控属性(Observables) knockout的三个核心特点: 1.监控属性与依赖跟踪 2.声明式绑定 3.模板 本页,你将学习上述三个特性.但是在这之前,先了解一下MVVC模式,及 视图模型( ...

  7. Spring MVC 学习总结(九)——Spring MVC实现RESTful与JSON(Spring MVC为前端提供服务)

    很多时候前端都需要调用后台服务实现交互功能,常见的数据交换格式多是JSON或XML,这里主要讲解Spring MVC为前端提供JSON格式的数据并实现与前台交互.RESTful则是一种软件架构风格.设 ...

  8. SpringCloud用户自定义配置信息的定义和查看

    一.概念 在SpringCloud项目中,用户自己定义的配置信息也可以放在application.*,需要以 info打头,以便使用公用基础设施 /info 查看! 本文讲解基于 ConfigServ ...

  9. Spring提取@Transactional事务注解的源码解析

    声明:本文是自己在学习spring注解事务处理源代码时所留下的笔记: 难免有错误,敬请读者谅解!!! 1.事务注解标签 <tx:annotation-driven /> 2.tx 命名空间 ...

  10. APDL link180单元

    目录 APDL代码实现link180单元的使用 结果图片 APDL代码实现link180单元的使用 由于不知道怎样使用LINK180单元,故按照相关的教程和理解,整理了一下比较完整的APDL的代码.其 ...