Android ListView避免多线程加载一个同一资源
当我们的ListView中的Item包含图片,而且这些图片是同一资源,我们用多线程去加载图片,这时候可能就发生了这种情况。
比如线程是人,第一个人去做加载图片到缓存的工作,还没做好时第二个人要这同一张张图,结果缓存还没有这张图,于是第二个人也去加载图片到缓存。。以此类推,同时可能有N个人在加载同一张图,N取决于图片没加载到缓存前,可见的Item数量。
于是针对这种情况进行细化同步,避免发生。
//首先需要一个ConcurrentHashMap<String, Boolean>,String表示资源地址如图片地址,Boolean表示是否有线程正在加载。
//之所以用ConcurrentHashMap,是因为它不但是同步的而且效率高于Synchronized和ReenTrantLock.
private ConcurrentHashMap<String, Boolean> mConcurentMap;
//然后需要一个ReentrantLock锁住线程内的关键判断语句。
private ReentrantLock mLock;
当一个线程没有在缓存找到资源,那么将读取资源,ConcurrentHashMap记录这个资源地址,并且Boolean为true,表示有人在干这个活了,下面的人只要等待干活的人干完就行了。
//这是加载图片的线程,当缓存中没找到图片(mBitmapCache.get(path) == null)进入此线程
Thread thread = new Thread() {
@Override
public void run() {
mLock.lock();//锁住关键判断逻辑,避免同一资源多个线程都进入false逻辑(加载图片)
if (mConcurentMap.get(path) == false) {
// mConcurentMap添加键值对,表示path这个资源已经有人在加载了
mConcurentMap.put(path, true);
mLock.unlock(); //释放锁,下面进入的线程只能进入true的逻辑(等待第一个人做完工作)
if (path != null && (!path.equals("null")) && (!"".equals(path))) {
//加载图片
item.bm = PictureHelper.getCropImage(path, , true, ,mActivity, , true);
//图片加载完放入缓存Lrucache
mBitmapCache.put(path, item.bm);
//设置键值对,false表示path这个资源已经加载完,或者没人加载了
mConcurentMap.put(path, false);
} else {
item.bm = null;
//图片地址无效
mConcurentMap.put(path, false);
}
Message msg = new Message();
msg.what = ;
handler.sendMessage(msg);
} else {
// 释放锁
mLock.unlock();
// 表示有人在加载图片,因此用死循环等待加载完成
while (true) {
// false表示加载完成,此时缓存已有图片,应该跳出循环
if (mConcurentMap.get(path) == false) {
// Logg.D("other need break cycle");
break;
}
}
// Logg.D("other go out cycle");
if (mBitmapCache.get(path) != null) {
item.bm = mBitmapCache.get(path);
Message msg = new Message();
msg.what = ;
handler.sendMessage(msg);
} else {
throw new NullPointerException("(mBitmapCache.get(path) == null!");
}
}
}
};
executors.execute(thread);
Android ListView避免多线程加载一个同一资源的更多相关文章
- android ListView上拉加载更多 下拉刷新功能实现(采用pull-to-refresh)
Android实现上拉加载更多功能以及下拉刷新功能, 采用了目前比较火的PullToRefresh,他是目前实现比较好的下拉刷新的类库. 目前他支持的控件有:ListView, ExpandableL ...
- Android 编程下 WebView 加载一个网页如何得到网页的 Cookie 值
http://www.cnblogs.com/sunzn/archive/2013/04/03/2998113.html mWebView.setWebViewClient(new MyWebView ...
- Android ListView 图片异步加载和图片内存缓存
开发Android应用经常需要处理图片的加载问题.因为图片一般都是存放在服务器端,需要联网去加载,而这又是一个比较耗时的过程,所以Android中都是通过开启一个异步线程去加载.为了增加用户体验,给用 ...
- 实现动态加载一个 JavaScript 资源
var script = document.createElement("script"); var head = document.getElementsByTagName(&q ...
- Android Listview异步动态加载网络图片
1.定义类MapListImageAndText管理ListViewItem中控件的内容 package com.google.zxing.client.android.AsyncLoadImage; ...
- Android基本控件之listView(三)<用ListView实现分页加载>
我们之前讨论了ListView的基本使用方法和ListView的优化 今天我们再来讨论一个关于ListView的一个新的东西~就是分页加载.那么什么是分页加载呢?简单点说,就是"下拉刷新&q ...
- android开发之Fragment加载到一个Activity中
Fragments 是android3.0以后添加的.主要是为了方便android平板端的开发.方便适应不同大小的屏幕.此代码是为了最简单的Fragment的使用,往一个Activity中添加Frag ...
- 转: listview异步图片加载之优化篇(android)
Listview异步加载之优化篇 关于listview的异步加载,网上其实很多示例了,总体思想差不多,不过很多版本或是有bug,或是有性能问题有待优化.有鉴于此,本人在网上找了个相对理想的版本并在此基 ...
- Android常用的图片加载库
Android常用的图片加载库 前言:图片加载涉及到图片的缓存.图片的处理.图片的显示等.四种常用的图片加载框架,分别是Fresco.ImageLoader. Picasso. Glide. Uni ...
随机推荐
- linux端口与进程命令
1 lsof命令 lsof -i:portNum 查出来与该端口相关的所有程序 2 netstat命令: netstat -lnp
- PLSQL往Oracle数据库插入中文后变为问号 和 启动PLSQL时提示NLS_LANG在客户端不能确定的解决办法
PLSQL往Oracle数据库插入中文后变为问号 和 启动PLSQL时提示NLS_LANG在客户端不能确定的解决办法 1.检查服务器的字符编码 Select * from V$NLS_PARAMETE ...
- ES6学习笔记(十四)
1.Promise的含义 Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理和更强大.它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Prom ...
- 使用PHP获取汉字的拼音(全部与首字母)
<?php /** * 取汉字拼音 * edit by www.jbxue.com */ class GetPingYing { private $pylist = array( 'a'=> ...
- MSP430F4152串口操作
/**********************************************************************/ /* 名称:串口通讯 功能:将接到的数据组后原封不 ...
- 阿里云服务器无法远程其他的mysql服务器
1.初始化root密码 进入mysql数据库 1 mysql>update user set password=PASSWORD('123456') where User='root'; 2.允 ...
- 1010. Radix (25)
Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The an ...
- ubuntu 设置显示器的亮度
ubuntu电脑重新启动后,亮度都变成了最亮.似乎也没胡地方可以设置.只好通过写个脚本来做这个事了. # -*- coding: utf-8 -*- import dbus bus = dbus.Se ...
- js 操作cookie
jquery.cookie中的操作: jquery.cookie.js是一个基于jquery的插件,点击下载! 创建一个会话cookie: $.cookie(‘cookieName’,'cookieV ...
- install ruby and ruby gem
sudo apt-get install ruby #find an folder and: git clone https://github.com/rubygems/rubygems.git cd ...