android使用LruCache对listview加载图片时候优化处理
时间:2022-04-25
本文章向大家介绍android使用LruCache对listview加载图片时候优化处理,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
注意:LruCache是有版本限制的,低版本的sdk需要在libs文件夹添加相应的support-4v文件。 本文改造的大部分是参考http://www.iteye.com/topic/1118828,感谢。 不废话直接上工程代码,内有关键注释,项目就不上传了,自己对照着上面网址改呗。
首先是Application文件,负责创建图片存储文件夹:
public class MyApp extends Application{
@Override
public void onCreate() {
super.onCreate();
File f = new File(Environment.getExternalStorageDirectory()+"/TestSyncListView/pic/");
if (!f.exists()) {
f.mkdirs();
}
}
}
图像读取工具类:
public class SyncImageLoaderUtil
{
private Object
lock = new Object();
private boolean mAllowLoad
= true;
private boolean firstLoad
= true;
private int mStartLoadLimit
= 0;
private int mStopLoadLimit
= 0;
final Handler
handler = new Handler();
//
private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
private LruCache<String,Bitmap>
mMemoryCache;
RunInOtherThread
runInOutherThread;
public SyncImageLoaderUtil(Context
context) {
super();
int memClass
= ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
int cacheSize
= 1024 *1024 *memClass
/ 8;
mMemoryCache
= new LruCache<String,
Bitmap>(cacheSize){
@Override
protected int sizeOf(String
key, Bitmap value) {
//
TODO Auto-generated method stub
return value.getRowBytes();
}
};
runInOutherThread
= new RunInOtherThread();
runInOutherThread.start();
}
public interface OnImageLoadListener
{
public void onImageLoad(Integer
t, Drawable drawable);
public void onError(Integer
t);
}
public void setLoadLimit(int startLoadLimit,int stopLoadLimit)
{
if (startLoadLimit
> stopLoadLimit) {
//
LogUtil.i("test", startLoadLimit+"--错误---"+stopLoadLimit);
return;
}
mStartLoadLimit
= startLoadLimit;
mStopLoadLimit
= stopLoadLimit;
}
public void restore()
{
mAllowLoad
= true;
firstLoad
= true;
}
public void lock()
{
mAllowLoad
= false;
firstLoad
= false;
}
public void unlock()
{
mAllowLoad
= true;
synchronized (lock)
{
lock.notifyAll();
}
}
public void loadImage(Integer
t, String imageUrl,
OnImageLoadListener
listener) {
final OnImageLoadListener
mListener = listener;
final String
mImageUrl = imageUrl;
final Integer
mt = t;
runInOutherThread.getHandler().post(new Runnable()
{
@Override
public void run()
{
if (!mAllowLoad)
{
synchronized (lock)
{
try {
lock.wait();
}catch (InterruptedException
e) {
//
TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if (mAllowLoad
&& firstLoad) {
loadImage(mImageUrl,
mt, mListener);
}
//
LogUtil.e("test", "原始开始:"+mStartLoadLimit+"原始当前位置:"+mt+"原始结束:"+mStopLoadLimit);
if (mAllowLoad
&& mt <= mStopLoadLimit && mt >= mStartLoadLimit) {
//
LogUtil.e("test", "开始:"+mStartLoadLimit+"当前位置:"+mt+"结束:"+mStopLoadLimit);
loadImage(mImageUrl,
mt, mListener);
}
}
});
}
private void loadImage(final String
mImageUrl, final Integer
mt,
final OnImageLoadListener
mListener) {
if (mImageUrl!=null &&
mMemoryCache.get(mImageUrl)!=null)
{
//
SoftReference<Drawable> softReference = imageCache.get(mImageUrl);
final Drawable
d = new BitmapDrawable(mMemoryCache.get(mImageUrl));
//
LogUtil.d("ppp", "drawable:"+d);
if (d
!= null)
{
handler.post(new Runnable()
{
@Override
public void run()
{
if (mAllowLoad)
{
mListener.onImageLoad(mt,
d);
}
}
});
return;
}
}
try {
final Drawable
d = loadImageFromUrl(mImageUrl);
if (d
!= null)
{
mMemoryCache.put(mImageUrl,
((BitmapDrawable)d).getBitmap());
}
handler.post(new Runnable()
{
@Override
public void run()
{
if (mAllowLoad)
{
mListener.onImageLoad(mt,
d);
}
}
});
}catch (IOException
e) {
handler.post(new Runnable()
{
@Override
public void run()
{
mListener.onError(mt);
}
});
e.printStackTrace();
}
}
public static Drawable
loadImageFromUrl(String url) throws IOException
{
//DebugUtil.debug(url);
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED))
{
File
f = new File(Environment.getExternalStorageDirectory()
+"/Weiyu/pic/" +
MD5Util.getMD5(url.getBytes()));
if (f.exists())
{
FileInputStream
fis = new FileInputStream(f);
Drawable
d = Drawable.createFromStream(fis, "src");
return d;
}
URL
m = new URL(url);
InputStream
i = (InputStream) m.getContent();
DataInputStream
in = new DataInputStream(i);
FileOutputStream
out = new FileOutputStream(f);
byte[]
buffer = new byte[1024];
int byteread
= 0;
while ((byteread
= in.read(buffer)) != -1)
{
out.write(buffer,0,
byteread);
}
in.close();
out.close();
return loadImageFromUrl(url);
}else {
URL
m = new URL(url);
InputStream
i = (InputStream) m.getContent();
Drawable
d = Drawable.createFromStream(i, "src");
return d;
}
}
}
线程辅助类:
public class RunInOtherThread
{
private static final String
LOG_TAG = "RunInOtherThread";
private LooperThread
localThread = new LooperThread();
private boolean isRunning
= true;
public Handler
getHandler(){
return localThread.getHandler();
}
private class LooperThreadextends Thread
{
private Handler
mHandler;
public void run()
{
Looper.prepare();
mHandler
= new Handler()
{
public void handleMessage(Message
msg) {
onReceiveMessage(msg.what);
}
};
Looper.loop();
}
Handler
getHandler(){
return mHandler;
}
}
public void start(){
localThread.start();
}
public void quit(){
localThread.getHandler().getLooper().quit();
}
public void sendMessage(int what){
getHandler().sendEmptyMessage(what);
}
public Thread
getThread(){
return localThread;
}
public void onReceiveMessage(int what){};
}
使用类:
//
实例化工具类
SyncImageLoaderUtil
syncImageLoader = new SyncImageLoaderUtil(mContext);
syncImageLoader.loadImage(position,
model.mPic, imageLoadListener);//应用接口:参数一是加载图片的位置;参数二是加载的ImageView;参数三是回调接口
//
map保存的键是位置,值是listview对应位置的布局
HashMap
map = new HashMap();
map.put(position,
convertView);
SyncImageLoaderUtil.OnImageLoadListener
imageLoadListener = new SyncImageLoaderUtil.OnImageLoadListener()
{
@Override
public void onImageLoad(Integer
t, Drawable drawable) {
View
view = (View) map.get(t);
if (view
!= null)
{
ImageView
iv = (ImageView) view.findViewById(R.id.image);
iv.setBackgroundDrawable(drawable);
}
}
@Override
public void onError(Integer
t) {
//
图片加载失败
//
取得listview对应的位置的行的内容布局
MusicModel
model = (MusicModel) getItem(t);
View
view = mListView.findViewWithTag(model);
if (view
!= null)
{
ImageView
iv = (ImageView) view.findViewById(R.id.image);
iv.setBackgroundResource(R.drawable.img_pic);
}
}
};
//
实现类而且需要实现OnScrollListener接口
public void loadImage()
{
//
不要在这里使用listview的getFirstVisiblePosition方法,位置不准
if (end
>= getCount()) {
end
= getCount() - 1;
}
syncImageLoader.setLoadLimit(start,
end);
syncImageLoader.unlock();
}
@Override
public void onScrollStateChanged(AbsListView
view, int scrollState)
{
//
TODO Auto-generated method stub
if (lodingView)
{
switch (scrollState)
{
case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
syncImageLoader.lock();
break;
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
loadImage();
break;
case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
syncImageLoader.lock();
break;
default:
break;
}
}
}
@Override
public void onScroll(AbsListView
view, int firstVisibleItem,
int visibleItemCount,int totalItemCount)
{
//
在这里取得的位置较准确,不过也会出现特殊的奇疤机型是不行的
//
start与end是定义的变量
start
= firstVisibleItem;
end
= firstVisibleItem + visibleItemCount;
if (firstVisibleItem
!= 0)
{
//
lodingView是控制变量,用来控制第一次进来视图加载读取图片
lodingView
= true;
}else {
lodingView
= false;
loadImage();
}
}
- BZOJ 3211: 花神游历各国【线段树区间开方问题】
- WP、Win10开发或者WPF开发时绘制自定义窗体~例如:一个手机
- 【Java学习笔记之八】JavaBean中布尔类型使用注意事项
- BZOJ 1597: [Usaco2008 Mar]土地购买【斜率优化+凸包维护】
- BZOJ 1046: [HAOI2007]上升序列【贪心+二分状态+dp+递归】
- 【Java学习笔记之九】java二维数组及其多维数组的内存应用拓展延伸
- BZOJ 1293: [SCOI2009]生日礼物【单调队列】
- Javascript缓存投毒学习与实战
- 【Java学习笔记之十】Java中循环语句foreach使用总结及foreach写法失效的问题
- Codeforces 839B Game of the Rows【贪心】
- Codeforces 839A Arya and Bran【暴力】
- 【Java学习笔记之十一】Java中常用的8大排序算法详解总结
- 浅谈zip格式处理逻辑漏洞
- C/C++中peek函数的原理及应用
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 七日Python之路--第二天
- 八、通过断点调试观察JS执行过程
- 传智播客OA项目学习--阶段三(Struts中Action书写)
- 九、函数与函数式编程
- 关于Hibernate懒加载----Spring filter
- 十、详解函数柯里化
- Unable to load file:*struts.xml-[unknown location]
- 使用hooks重新定义antd pro想象力(一)
- 传智播客OA项目学习--阶段三(级联操作)
- 七日Python之路--第十一天
- 使用hooks重构antd pro的想象力(三)我是如何利用hooks干掉redux的
- 七日Python之路--第十天
- 初学Vue.js,用 vue ui 创建项目会不会被鄙视
- 十三、jQuery过时的今天,你还会使用它吗
- 0005 Java 包扫描实现和应用(Jar篇)