关闭

Android异步加载学习笔记之四:利用缓存优化网络加载图片及ListView加载优化

标签: android开发AsyncTaskListView优化
932人阅读 评论(0) 收藏 举报
分类:

       如果不做任何处理,直接用网络加载图片在网速快的情况下可能没什么不好的感觉,但是如果使用移动流量或是网络不好的时候,问题就来了,要么用户会抱怨流量使用太多,要么抱怨图片加载太慢,如论从哪个角度出发,都不是好的体验!要提高用户体验,我们就要使用缓存。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;
}
}

0
0
查看评论

android图片轮播第一弹_异步获取和本地获取图片_轻量级可集成到项目中型

之前因为项目需要,要做一个类似于金融app上的图片轮播,后来我才发现原来很多的软件都需要用到这个功能,我到网上查了很多类似的控件,可是当我用的时候时候发现很多要么是太复杂,要么是有一些bug,还有一些非要用到Universal_Image_loader或者一些第三方的lib包,我就很不理解,我就是想...
  • u011077027
  • u011077027
  • 2016-03-01 13:30
  • 785

网络环境较差时,优化网络加载图片

思路:从加载图片的本身和手机的存储两方面考虑 解决办法: 1.找现有图片格式的替换着 在众多的图片格式中,选择Google的WebP。理由:压缩效率高,而且对android的支持更优秀,使用WebP后,相对于JPG格式的图片,流量节省了将近25%到35%; 相对于PNG格式的图片,流量节省了...
  • zzc901205
  • zzc901205
  • 2016-09-26 15:46
  • 426

Android网络图片加载优化

当我们使用淘宝app浏览产品的时候(很多其他app也是如此),就会发现每次下拉产品目录进行更新加载新图片的时候,都是出现对应的Item的时,才开始从网络下载并加载图片,从而出现很长的延时~
  • chen52671
  • chen52671
  • 2015-03-28 21:44
  • 1710

android listview异步加载图片

Android中的ListView是一个非常常用的控件,但是它却并不像想象中的那么简单。特别是当你需要在ListView中展示大量网络图片的时候,处理不好轻则用户体验不佳,重则OOM,异步线程丢失或者图片错位。 关于其中的OOM和异步线程丢失的问题,是一个很庞大的话题,本人能力有限,无法说清,只有...
  • cike110120
  • cike110120
  • 2013-05-26 11:58
  • 12958

浅谈Android中的异步加载之ListView中图片的缓存及优化三

隔了很久没写博客,现在必须快速脉动回来。今天我还是接着上一个多线程中的异步加载系列中的最后一个使用异步加载实现ListView中的图片缓存及其优化。具体来说这次是一个综合Demo.但是个人觉得里面还算有点价值的就是里面的图片的缓存的实现。因为老实说它确实能在实际的项目中得到很好的应用。主要学习来源于...
  • u013064109
  • u013064109
  • 2016-06-25 02:56
  • 6519

Android开发之listview优化+图片异步加载+避免图片显示闪烁(修改版)

小鹿路过此地。。心热之下写写我li
  • lusiting
  • lusiting
  • 2014-10-19 12:24
  • 1302

android 视频的缩略图 缓存机制和 异步加载缩略图

在这次的工作开发项目中,涉及到一个视频缩略图的视频列表;这个在大家看来,制作视频缩略图就是两行代码就搞定的事。确实是这样的,百度一下,每个帖子都知道制作视频缩略图的方法,在这里确实也是一样的,但是我要实现的是让缩略图 在ListView上显示,而且不会出现卡顿,其实也不是特别难,确实很实用;主要的实...
  • CSDN_LQR
  • CSDN_LQR
  • 2016-05-15 16:32
  • 627

Android 解决ListView异步加载网络数据(图片文字)出现位置错乱以及优化ListView的加载

Android 多种方法解决以及优化ListView的加载网络数据程出现错乱的问题 1.普通的缓存机制存在的问题 下面的代码就是最常见的异步加载图片的方法: public View getView(int i, View vi...
  • zhangtao19931104
  • zhangtao19931104
  • 2016-10-05 17:07
  • 905

深入剖析Android之ListView从网络异步加载图片

深入剖析Android之ListView从网络异步加载图片 我写这篇博客参考了许多文章,其中要重点感谢的是Android ListView从网络获取图片及文字显示和他的英文版文章Android Custom ListView with Image and Text 布局篇 先来看一下做出来之后的效...
  • benbendeda
  • benbendeda
  • 2015-01-26 22:24
  • 2166

Android图片加载优化--图片缓存

转载请注明出处:作者CJstar为什么要使用内存缓存 内存缓存: 内存缓存是指将已经赋值的对象保存在内存中,当再次使用的时候直接去内存读取,不再做重复的创建操作。 内存缓存的优势: 对象的重复使用,不再去创建对象,减少内存消耗,便于内存的集中管理。同时在需要读取数据库或者外存的时候,使用内存缓...
  • CJ_star
  • CJ_star
  • 2015-09-17 19:52
  • 1027
    个人资料
    • 访问:893902次
    • 积分:11983
    • 等级:
    • 排名:第1481名
    • 原创:343篇
    • 转载:59篇
    • 译文:1篇
    • 评论:250条
    Github
    个人Github主页面:https://github.com/ldm520,请大家多指教!
    最新评论