Android引入高速缓存的异步加载全分辨率
Android引进高速缓存的异步加载全分辨率
为什么要缓存
内存缓存
内存缓存技术对那些大量占用应用程序宝贵内存的图片提供了高速訪问的方法。当中最核心的类是LruCache 。这个类非常适合用来缓存图片,它的主要算法原理是把近期使用的对象用强引用存储在 LinkedHashMap 中,并且把近期最少使用的对象在缓存值达到预设定值之前从内存中移除。LruCache 是在support-v4中才引入的,在引入LruCache 之前。Google建议的是使用软引用或弱引用 (SoftReference or WeakReference)来进行内存缓存。可是从Android 2.3開始,GC算法改动,软引用与弱引用相同会优先被GC回收。所以这样的方法也就没有太高的使用价值了,如今网上非常多还在继续使用SoftReference 和WeakReference的文章。大多都是过时的文章,建议大家跟上党的步伐,与时俱进。
LruCache使用
这个平衡点常常须要非常多经验和測试来决定。
使用LruCache非常easy:
private LruCache<String, Bitmap> mMemoryCaches; // 获取应用内存
int maxMemory = (int) Runtime.getRuntime().maxMemory();
// 分配cache
int cacheSize = maxMemory / 10;
mMemoryCaches = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
}; // 从LruCache获取中获取缓存对象
public Bitmap getBitmapFromMemoryCaches(String url) {
return mMemoryCaches.get(url);
} // 添加缓存对象到LruCache
public void addBitmapToMemoryCaches(String url,Bitmap bitmap) {
if (getBitmapFromMemoryCaches(url) == null) {
mMemoryCaches.put(url, bitmap);
}
}
首先,我们须要声明LruCache。接着。通过LruCache的构造方法创建缓存对象,并为其分配cacheSize,这个cacheSize通常我们须要通过Runtime来获取,获取当前系统分给App的可用内存,并将这些内存的一部分用做LruCache缓存。LruCache中必须重写sizeOf方法。通过这种方法,LruCache能够获取每一个缓存对象的大小。子类必须重写。由于默认的LruCache获取的是缓存的个数。
。。尼玛。
为异步处理添加一级缓存
滚完再载入
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
mImageLoader.loadImages(mStart, mEnd);
} else {
mImageLoader.cancelAllTasks();
}
} @Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
mStart = firstVisibleItem;
mEnd = firstVisibleItem + visibleItemCount;
if (mFirstFlag && visibleItemCount > 0) {
mImageLoader.loadImages(mStart, mEnd);
mFirstFlag = false;
}
}
载入显示的项目
public void loadImages(int start, int end) {
for (int i = start; i < end; i++) {
String url = Images.IMAGE_URLS[i];
Bitmap bitmap = getBitmapFromMemoryCaches(url);
if (bitmap == null) {
ASyncDownloadImage task = new ASyncDownloadImage(url);
mTasks.add(task);
task.execute(url);
} else {
ImageView imageView = (ImageView) mListView.findViewWithTag(url);
imageView.setImageBitmap(bitmap);
}
}
}
这里我们在设置图片的时候,直接通过findViewWithTag。通过url来找到相应的Imageview,这里与之前不同是由于我们这里是依照start到end来进行载入,直接从ListView对象中获取相应的Imageview比較简单。
下载与Asynctask
private static Bitmap getBitmapFromUrl(String urlString) {
Bitmap bitmap;
InputStream is = null;
try {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
is = new BufferedInputStream(conn.getInputStream());
bitmap = BitmapFactory.decodeStream(is);
conn.disconnect();
return bitmap;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
}
}
return null;
}
Asynctask也与之前基本相似:
class ASyncDownloadImage extends AsyncTask<String, Void, Bitmap> {
private String url;
public ASyncDownloadImage(String url) {
this.url = url;
}
@Override
protected Bitmap doInBackground(String... params) {
url = params[0];
Bitmap bitmap = getBitmapFromUrl(url);
if (bitmap != null) {
addBitmapToMemoryCaches(url, bitmap);
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
ImageView imageView = (ImageView) mListView.findViewWithTag(url);
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
mTasks.remove(this);
}
}
唯一不同的是。我们在下载好图像之后。会将图像载入到Lrucache。
组装
package com.imooc.listviewacyncloader; import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.LruCache;
import android.widget.ImageView;
import android.widget.ListView; import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashSet;
import java.util.Set; public class ImageLoaderWithCaches { private Set<ASyncDownloadImage> mTasks;
private LruCache<String, Bitmap> mMemoryCaches;
private ListView mListView; public ImageLoaderWithCaches(ListView listview) {
this.mListView = listview;
mTasks = new HashSet<>();
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 10;
mMemoryCaches = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
} public void showImage(String url, ImageView imageView) {
Bitmap bitmap = getBitmapFromMemoryCaches(url);
if (bitmap == null) {
imageView.setImageResource(R.drawable.ic_launcher);
} else {
imageView.setImageBitmap(bitmap);
}
} public Bitmap getBitmapFromMemoryCaches(String url) {
return mMemoryCaches.get(url);
} public void addBitmapToMemoryCaches(String url,Bitmap bitmap) {
if (getBitmapFromMemoryCaches(url) == null) {
mMemoryCaches.put(url, bitmap);
}
} public void loadImages(int start, int end) {
for (int i = start; i < end; i++) {
String url = Images.IMAGE_URLS[i];
Bitmap bitmap = getBitmapFromMemoryCaches(url);
if (bitmap == null) {
ASyncDownloadImage task = new ASyncDownloadImage(url);
mTasks.add(task);
task.execute(url);
} else {
ImageView imageView = (ImageView) mListView.findViewWithTag(url);
imageView.setImageBitmap(bitmap);
}
}
} private static Bitmap getBitmapFromUrl(String urlString) {
Bitmap bitmap;
InputStream is = null;
try {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
is = new BufferedInputStream(conn.getInputStream());
bitmap = BitmapFactory.decodeStream(is);
conn.disconnect();
return bitmap;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
}
}
return null;
} public void cancelAllTasks() {
if (mTasks != null) {
for (ASyncDownloadImage task : mTasks) {
task.cancel(false);
}
}
} class ASyncDownloadImage extends AsyncTask<String, Void, Bitmap> { private String url; public ASyncDownloadImage(String url) {
this.url = url;
} @Override
protected Bitmap doInBackground(String... params) {
url = params[0];
Bitmap bitmap = getBitmapFromUrl(url);
if (bitmap != null) {
addBitmapToMemoryCaches(url, bitmap);
}
return bitmap;
} @Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
ImageView imageView = (ImageView) mListView.findViewWithTag(url);
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
mTasks.remove(this);
}
}
}
以下是Adapter的代码:
package com.imooc.listviewacyncloader; import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView; import java.util.List; public class MyAdapterUseCaches extends BaseAdapter implements
AbsListView.OnScrollListener { private LayoutInflater mInflater;
private List<String> mData;
private ImageLoaderWithCaches mImageLoader;
private int mStart = 0, mEnd = 0;
private boolean mFirstFlag; public MyAdapterUseCaches(Context context, List<String> data, ListView listView) {
this.mData = data;
mInflater = LayoutInflater.from(context);
mImageLoader = new ImageLoaderWithCaches(listView);
mImageLoader.loadImages(mStart, mEnd);
mFirstFlag = true;
listView.setOnScrollListener(this);
} @Override
public int getCount() {
return mData.size();
} @Override
public Object getItem(int position) {
return mData.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
String url = mData.get(position);
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.listview_item, null);
viewHolder.imageView =
(ImageView) convertView.findViewById(R.id.iv_lv_item);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.imageView.setTag(url);
viewHolder.imageView.setImageResource(R.drawable.ic_launcher);
mImageLoader.showImage(url, viewHolder.imageView);
return convertView;
} @Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
mImageLoader.loadImages(mStart, mEnd);
} else {
mImageLoader.cancelAllTasks();
}
} @Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
mStart = firstVisibleItem;
mEnd = firstVisibleItem + visibleItemCount;
if (mFirstFlag && visibleItemCount > 0) {
mImageLoader.loadImages(mStart, mEnd);
mFirstFlag = false;
}
} public class ViewHolder {
public ImageView imageView;
}
}
是不是非常easy,如今引入缓存了,下载过的图片会临时保存在内存中。妈妈再也不用操心你OOM啦。

版权声明:本文博主原创文章。博客,未经同意不得转载。
Android引入高速缓存的异步加载全分辨率的更多相关文章
- [Android Pro] 使用CursorLoader异步加载数据 from 3.0
Android 3.0引入了CursorLoader实现异步加载数据,为了避免同步查询数据库时阻塞UI线程的问题.在API 11之前可以通过下载支持库,来使之前的系统支持此功能,下载页面为 http: ...
- Android之使用Android-AQuery异步加载图片(一)
第一节:转载地址(http://www.cnblogs.com/lee0oo0/archive/2012/10/25/2738299.html) // 必须实现AQuery这个类 AQuery aq ...
- (转)Android技术积累:图片异步加载
当在ListView或GridView中要加载很多图片时,很容易出现滑动时的卡顿现象,以及出现OOM导致FC(Force Close). 会出现卡顿现象主要是因为加载数据慢,要等数据加载完才能显示出来 ...
- Android中图片的异步加载
转: 1. 为什么要异步加载图片 下载图片比较费时,先显示文字部分,让加载图片的过程在后台,以提升用户体验 2. SoftReference的作用 栈内存—引用 堆内存—对象 Eg: Object ...
- Android异步加载图像(含线程池,缓存方法)
研究了android从网络上异步加载图像: (1)由于android UI更新支持单一线程原则,所以从网络上取数据并更新到界面上,为了不阻塞主线程首先可能会想到以下方法. 在主线程中new 一个Han ...
- 转: Android异步加载图像小结
转:http://blog.csdn.net/sgl870927/article/details/6285535 研究了android从网络上异步加载图像,现总结如下: (1)由于android UI ...
- Android图片异步加载之Android-Universal-Image-Loader
将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...
- [置顶] Android图片异步加载之Android-Universal-Image-Loader
将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...
- ListView与GridView异步加载图片
原理很简单,主要是用到了回调方法,下面是异步加载图片的类 <span style="font-size:16px;">package com.xxx.xxx; impo ...
随机推荐
- hadoop学习;大数据集在HDFS中存为单个文件;安装linux下eclipse出错解决;查看.class文件插件
sudo apt-get install eclipse 安装后打开eclipse,提示出错 An error has occurred. See the log file /home/pengeor ...
- Android仿WIN8系统磁贴点击下沉倾斜效果
※效果 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGluZ2xvbmd4aW4yNA==/font/5a6L5L2T/fontsize/400/fil ...
- LAMP配置参考地址
http://www.linuxidc.com/Linux/2014-07/104563.htm
- Codeforces 191 C Fools and Roads (树链拆分)
主题链接~~> 做题情绪:做了HDU 5044后就感觉非常easy了. 解题思路: 先树链剖分一下,把树剖分成链,由于最后全是询问,so~能够线性操作.经过树链剖分后,就会形成很多链,可是每条边 ...
- asp.net Login控件基本属性及事件说明
原文:asp.net Login控件基本属性及事件说明 Login系列控件是微软为了简化我们的开发过程,为我们进行常规的安全开发提供块捷途径. Login系列控件包含下列控件: Login 登录控件 ...
- HorizontalScrollView做页卡的一个小记录
用HorizontalScrollView做页卡,实现一个如下图的效果:
- Android ImageButton Example 图片按钮
Android ImageButton Example 图片按钮 使用“android.widget.ImageButton” 展现一个具有背景图片的按钮 本教程将展现一个具有名字为 c.png背景图 ...
- Android正在使用Handler实现信息发布机制(一)
上一篇文章,我们谈到了电话Handler的sendMessage方法,最后,我们将进入一个电话 sendMessageAtTime方法,例如下列: public boolean sendMessage ...
- 概率dp专辑
求概率 uva11021 http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...
- Android:刚6瓶啤酒4两56度白酒下肚,竟然20分钟做了一手机版站点 !
刚6瓶啤酒4两56度白酒下肚,竟然20分钟不到时间做了一手机版站点 !人有多大潜力你知道吗? 大家有兴趣的能够用手机或微信打开 http://xh.yunxunmi.com/ 看看俺这酒后之做! 很 ...