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 ...
随机推荐
- location跳转和header跳转的区别
1:header("location:url") 跳转之前不能有任何输出,如果想在header之前有输出,则要修改php.ini文件.具体 output_handler =mb_o ...
- JQuery淡入淡出 banner切换特效
附件中提供另一种实现方式 基本类似 主要的实现方法如下: var ShowAD=function(i){ showImg.eq(i).animate({opacity:1},settings.sp ...
- RadComboBox的用法
AutoPostBack="true",自动回传数据,也就是自动刷新 <telerik:RadComboBox ID="rcbTeacherList" r ...
- Ubuntu系统启动时waiting for network
最近在使用Ubuntu时启动经常会遇到等待网络配置, 每次等待时间都很长,要几分钟,于是在网上看看其他大牛怎么解决该问题. 有些解决方法中有提到删除 网卡硬件信息文件/etc/udev/rules.d ...
- PHP视频教程 > PHP面向对象编程视频教程
当前位置: 主页 > 编程开发 > PHP视频教程 > PHP面向对象编程视频教程 > kingstone金士顿手机内存卡16G仅65元 1.1.什么是面向对象和类 上传日期: ...
- 【socket】Socket的三个功能类TCPClient、TCPListener 和 UDPClient
Socket的三个功能类TCPClient.TCPListener 和 UDPClient (转) 应用程序可以通过 TCPClient.TCPListener 和 UDPClient 类使用传输控制 ...
- easy ui datagrid 增,删,改,查等基本操作
如下图: ①列表信息图 ②添加信息图 ③修改信息图 html代码: <%@ Page Title="" Language="C#" MasterPageF ...
- Android模拟神器Genymotion eclipse插件安装问题出解决
我之前一直是打开eclipse之前直接运行Genymotion模拟器就可以连接到adb了,非常方便,但最近突然想来装个eclipse的Genymotion插件玩玩,安装时居然出错了,于是不折腾好心里不 ...
- ubuntu系统使用快捷键打开终端方式总结
ctrl + alt + T 三键齐下打开虚拟终端 ctrl + alt + F1 (~F6)打开系统终端ctrl + alt + F7 返回图形界面都可以使用exit命令关闭, 不同的是虚拟终端ex ...
- hdu 4648
求一个数列中 去掉一些连续的数之后 不改变对m取余后的值 就是求一个最长的连续子序列 对m取余后为0 我的方法可能比较水 #include<iostream> #include<c ...