假设不做不论什么处理。直接用网络载入图片在网速快的情况下可能没什么不好的感觉。可是假设使用移动流量或是网络不好的时候。问题就来了,要么用户会抱怨流量使用太多。要么抱怨图片载入太慢。如论从哪个角度出发,都不是好的体验!

要提高用户体验,我们就要使用缓存。Android中数据缓存的方式有非常多,相关介绍的文章也比較多。比方http://blog.csdn.net/dahuaishu2010_/article/details/17093139http://www.jb51.net/article/38162.htm等。今天学习是是Lru缓存。

Lru(Least Recently Used)近期最少使用算法,即是在一定条件下LRU缓存是把近期最少使用的数据移除。让给最新读取的数据。而往往最常读取的,也是读取次数最多的。所以。利用LRU缓存,我们可以提高应用的效率及用户体验度。Andorid本身提供了LruCache类来实现这个缓存算法 。

在ImageLoader中利用LruCache缓存:

public class ImageLoader {

private LruCache<String, Bitmap> mCaches;// 创建LruCache对象

private ImageView mImageView;

private ListView listView;

private Set<ImageAsyncTask> mTask;





@SuppressLint("NewApi")

public ImageLoader(ListView listView) {

this.listView = listView;

mTask = new HashSet<ImageAsyncTask>();

int maxMemory = (int) Runtime.getRuntime().maxMemory();// 获取最大可用内存

int cacheSize = maxMemory / 8;// 设置缓存数据的最大占用内存量为最大值1/8

mCaches = new LruCache<String, Bitmap>(cacheSize) {

@Override

protected int sizeOf(String key, Bitmap value) {

return value.getByteCount();// 每次存入缓存的时候调用,返回bitmap的大小

}

};

}





@SuppressLint("NewApi")

/**

* 添加缓存数据。添加前推断数据是否存在

* @description:

* @author ldm

* @date 2015-8-11 下午7:51:04

*/

public void setLruCaches(String url, Bitmap bitmap) {

if (getLruCaches(url) == null) {// 假设缓存中不存在url相应的Bitmap。则把bitmap增加mCaches

mCaches.put(url, bitmap);

}

}





/**

* 从缓存中获取数据

* @description:

* @author ldm

* @date 2015-8-11 下午7:51:22

*/

@SuppressLint("NewApi")

public Bitmap getLruCaches(String url) {

return mCaches.get(url);// 通过url获取缓存中相应的bitmap





}





/**

*从url中获取到Bitmap

* @description:

* @author ldm

* @date 2015-8-11 下午1:55:12

*/

public Bitmap getBitmapByUrl(String urlStr) {

Bitmap bitmap = null;

InputStream is = null;

try {

URL url = new URL(urlStr);

HttpURLConnection con = (HttpURLConnection) url.openConnection();

is = new BufferedInputStream(con.getInputStream());

bitmap = BitmapFactory.decodeStream(is);

con.disconnect();

return bitmap;

}

catch (Exception e) {

e.printStackTrace();

}

finally {

try {

is.close();

}

catch (IOException e) {

e.printStackTrace();

}

}

return null;

}





public void loadImgByAsyncTask(ImageView img, String url) {

mImageView = img;

// 从缓存中取出图片

Bitmap bitmap = getLruCaches(url);

if (bitmap == null) {// 假设能在中无图片,则就从网络下载

mImageView.setImageResource(R.drawable.ic_launcher);//设置默认图片

new ImageAsyncTask(url).execute(url);

}

else {// 缓存中有图片。则直接显示出来

mImageView.setImageBitmap(bitmap);

}

}





private class ImageAsyncTask extends AsyncTask<String, Void, Bitmap> {

private ImageView imageView;

private String mUrl;





public ImageAsyncTask(String mUrl) {

this.mUrl = mUrl;

}





@Override

protected Bitmap doInBackground(String... params) {

Bitmap bitmap = getBitmapByUrl(params[0]);// 获取图片

if (bitmap != null) {

setLruCaches(params[0], bitmap);

}

return getBitmapByUrl(params[0]);

}





@Override

protected void onPostExecute(Bitmap result) {

ImageView img = (ImageView) listView.findViewWithTag(mUrl);

if (img != null && result != null) {

imageView.setImageBitmap(result);

}

mTask.remove(this);

}

}





public void setImageView(int start, int end) {

for (int i = start; i < end; i++) {

String url = DataAdapter.URLS[i];

Bitmap bitmap = getLruCaches(url);

if (bitmap == null) {// 假设能在中无图片,则就从网络下载

ImageAsyncTask task = new ImageAsyncTask(url);

task.execute(url);

mTask.add(task);

}

else {// 缓存中有图片,则直接显示出来

ImageView img = (ImageView) listView.findViewWithTag(url);

img.setImageBitmap(bitmap);

}

}

}

public void stopAllTask(){

if(mTask.size()>0){

for (ImageAsyncTask task : mTask) {

task.cancel(false);

}

}

}

}

相应ListView的数据适配器DataAdapter:

public class DataAdapter extends BaseAdapter implements OnScrollListener {

private Context mContext;

private List<DataBean> list;

private ImageLoader mImageLoader;

private int mSart;

private int mEnd;

public static String[] URLS;

private ListView listView;

private boolean isFirst;//是否是第一次进入 

public DataAdapter(Context mContext, List<DataBean> list, ListView listView) {

this.listView = listView;

this.mContext = mContext;

this.list = list;

mImageLoader = new ImageLoader(listView);

URLS = new String[list.size()];

for (int i = 0; i < list.size(); i++) {

URLS[i] = list.get(i).getImgUrl();

}

isFirst=true;

listView.setOnScrollListener(this);

}



@Override

public int getCount() {

// TODO Auto-generated method stub

return list.size();

}



@Override

public Object getItem(int arg0) {

// TODO Auto-generated method stub

return list.get(arg0);

}



@Override

public long getItemId(int arg0) {

// TODO Auto-generated method stub

return arg0;

}



@Override

public View getView(int arg0, View view, ViewGroup arg2) {

ViewHolder holder = null;

if (view == null) {

holder = new ViewHolder();

view = LayoutInflater.from(mContext).inflate(R.layout.item_layout, null);

holder.iv = (ImageView) view.findViewById(R.id.item_iv);

holder.titleTv = (TextView) view.findViewById(R.id.item_title);

holder.contentTv = (TextView) view.findViewById(R.id.item_content);

view.setTag(holder);

}

else {

holder = (ViewHolder) view.getTag();

}

holder.titleTv.setText(list.get(arg0).getTitle());

holder.contentTv.setText(list.get(arg0).getContent());

holder.iv.setTag(list.get(arg0).getImgUrl());// 为ImageView设置tag

// new ImageLoader().loaderImageThread(holder.iv, list.get(arg0).getImgUrl());//用线程载入图片

mImageLoader.loadImgByAsyncTask(holder.iv, list.get(arg0).getImgUrl());

return view;

}



/***

* ListView在流动过程中调用 

*/

@Override

public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

mSart = firstVisibleItem;// 可见第一个item

mEnd = firstVisibleItem + visibleItemCount;// 可见的最后一个item

if(isFirst&&visibleItemCount>0){//第一次载入数据时数据处理

mImageLoader.setImageView(mSart, mEnd);

isFirst=false;

}

}



/***

* ListView在流动状态变化时调用 

*/

@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

if (scrollState == SCROLL_STATE_IDLE) {// 流动停止,此时载入可见项数据

mImageLoader.setImageView(mSart, mEnd);

}

else {// 停止载入数据

mImageLoader.stopAllTask();

}

}

class ViewHolder {

TextView titleTv;

TextView contentTv;

ImageView iv;

}

}

Android异步载入学习笔记之四:利用缓存优化网络载入图片及ListView载入优化的更多相关文章

  1. Android安装器学习笔记(一)

    Android安装器学习笔记(一) 一.Android应用的四种安装方式: 1.通过系统应用PackageInstaller.apk进行安装,安装过程中会让用户确认 2.系统程序安装:在开机的时候自动 ...

  2. 学习笔记:利用GDI+生成简单的验证码图片

    学习笔记:利用GDI+生成简单的验证码图片 /// <summary> /// 单击图片时切换图片 /// </summary> /// <param name=&quo ...

  3. 机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据

    机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据 关键字:PCA.主成分分析.降维作者:米仓山下时间:2018-11-15机器学习实战(Ma ...

  4. Spring MVC 学习笔记2 - 利用Spring Tool Suite创建一个web 项目

    Spring MVC 学习笔记2 - 利用Spring Tool Suite创建一个web 项目 Spring Tool Suite 是一个带有全套的Spring相关支持功能的Eclipse插件包. ...

  5. Oracle学习笔记之四sp1,Oracle 11g的常用函数

    从Oracle学习笔记之四,SQL语言入门中摘出来的,独立成一章节 3.1 字符类函数 ASCII(c)和CHR(i)    分别用于返回一个字符的ASCII码和返回给定ASCII值所对应的字符. C ...

  6. mybatis学习笔记(14)-查询缓存之中的一个级缓存

    mybatis学习笔记(14)-查询缓存之中的一个级缓存 标签: mybatis mybatis学习笔记14-查询缓存之中的一个级缓存 查询缓存 一级缓存 一级缓存工作原理 一级缓存測试 一级缓存应用 ...

  7. SpringBoot学习笔记:Redis缓存

    SpringBoot学习笔记:Redis缓存 关于Redis Redis是一个使用ANSI C语言编写的免费开源.支持网络.可基于内存亦可以持久化的日志型.键值数据库.其支持多种存储类型,包括Stri ...

  8. 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)

    再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...

  9. [Android]异步加载图片,内存缓存,文件缓存,imageview显示图片时增加淡入淡出动画

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3574131.html  这个可以实现ImageView异步加载 ...

随机推荐

  1. checkbox 多选框 :jquery之全选、全不选、反选

    javascriptjqueryselectAll [html] view plaincopy   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1 ...

  2. Spring Boot 使用Jar打包发布, 并使用 Embedded Jetty/Tomcat 容器

    Jar包发布 在项目pom.xml中, 如果继承了Spring Boot的starter parent, 那么默认已经包含打包需要的plugins了, 设置为jar就能直接打包成包含依赖的可执行的ja ...

  3. Centos7新装配置, 并使用openvpn client长连接远程备份

    1. 修改本机hostname // 查看本机hostname hostnamectl //永久性的修改主机名称, 修改完后新开的terminal中立刻生效. 也可以直接修改 /etc/hostnam ...

  4. 使用PowerDesigner生成SQL语句

    0.我使用的PowerDedigner的版本如下: 1.tools>>Resource>>DBMS,然后选中你的数据库版本,双击或点击左上角的properties. 2.再选择 ...

  5. Android API之Telephony.Sms

    Telephony.Sms Contains all text based SMS messages. 包含基于SMS消息的所有文本. 1.sms表结构. _ID _id INTEGER(long) ...

  6. git clone时RPC failed; curl 18 transfer closed with outstanding read data remaining

    git clone时报RPC failed; curl 18 transfer closed with outstanding read data remaining 错误 原因1:缓存区溢出 解决方 ...

  7. Linux-使用ctags、vim查看数据类型所在头文件

    安装 ctags yum -y install ctags 生成 tags 文件 cd /usr/include ctags -R . 在 vim 中配置 tags #修改 vim 配置文件.或者使用 ...

  8. Linux-配置虚拟IP

    Linux下配置网卡ip别名何谓ip别名?用windows的话说,就是为一个网卡配置多个ip.什么场合增加ip别名能派上用场?布网需要.多ip访问测试.特定软件对多ip的需要...and so on. ...

  9. cmd下查看端口被某程序占用命令

    经常,我们在启动应用的时候发现系统需要的端口被别的程序占用,如何知道谁占有了我们需要的端口,很多人都比较头疼,下面就介绍一种非常简单的方法,希望对大家有用 假如我们需要确定谁占用了我们的9050端口 ...

  10. 屏蔽alert弹框下面一层的操作

    需求: 给alert框戴个套. 屏蔽下层页面的操作. 搞这个花里胡哨的东西. 还一baidu全都是长得一样的答案. 神魔恋. /** * Tip Message像alert一样 */ function ...