- 浏览: 19270 次
- 性别:
- 来自: 深圳
最新评论
手机客户端以列表形式展示数据是非常常见的一种方式。然而列表中要显示图片(比如:头像)就要采用异步线程加载的方式,这样做是为了防止加载图片数据的时候,花费时间过长,阻塞UI线程,从而达到保持App的流畅性的目的。
下面我将分享
OSChina.NET
Android版客户端的列表异步线程加载图片的方法:
图片缓存
private static HashMap<String, SoftReference<Bitmap>> cache;
图片缓存是当有加载过相同的图片的时候,可以快速重复使用,比如同一个人的头像。 图片控件集合
private static Map<ImageView, String> imageViews;
图片控件集合是一个Map,记录当前ImageView控件对应的图片地址,用来防止异步线程加载图片时候ImageView控件显示的图片与实际图片地址对应的图片不符,出现错乱。
线程池
private static ExecutorService pool;
固定线程池里的并发线程数,可以防止用户在快速滑动列表的时候,不执行已经滑过去的加载线程。
具体的初始化代码:
static { cache = new HashMap<String, SoftReference<Bitmap>>(); pool = Executors.newFixedThreadPool(5); //固定线程池 imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); }
接下来,我们来看看具体是如何加载图片的:
public void loadBitmap(String url, ImageView imageView, Bitmap defaultBmp, int width, int height) { imageViews.put(imageView, url); Bitmap bitmap = getBitmapFromCache(url); if (bitmap != null) { //显示缓存图片 imageView.setImageBitmap(bitmap); } else { //加载SD卡中的图片缓存 String filename = FileUtils.getFileName(url); String filepath = imageView.getContext().getFilesDir() + File.separator + filename; File file = new File(filepath); if(file.exists()){ //显示SD卡中的图片缓存 Bitmap bmp = ImageUtils.getBitmap(imageView.getContext(), filename); imageView.setImageBitmap(bmp); }else{ //线程加载网络图片 imageView.setImageBitmap(defaultBmp); queueJob(url, imageView, width, height); } } }
上面的代码中,我们根据图片的url地址,先从图片缓存里面查找是否已缓存过,如果没有,再从SD卡的图片缓存文件中查找,如果再没有,最后才是加载网络图片。这才是以最快速的方式显示图片。
下面,我将贴出完整的代码:
/** * 异步线程加载图片工具类 * @author liux */ public class BitmapManager { private static HashMap<String, SoftReference<Bitmap>> cache; private static ExecutorService pool; private static Map<ImageView, String> imageViews; private Bitmap defaultBmp; static { cache = new HashMap<String, SoftReference<Bitmap>>(); pool = Executors.newFixedThreadPool(5); //固定线程池 imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); } public BitmapManager(){} public BitmapManager(Bitmap def) { this.defaultBmp = def; } /** * 设置默认图片 * @param bmp */ public void setDefaultBmp(Bitmap bmp) { defaultBmp = bmp; } /** * 加载图片 * @param url * @param imageView */ public void loadBitmap(String url, ImageView imageView) { loadBitmap(url, imageView, this.defaultBmp, 0, 0); } /** * 加载图片-可设置加载失败后显示的默认图片 * @param url * @param imageView * @param defaultBmp */ public void loadBitmap(String url, ImageView imageView, Bitmap defaultBmp) { loadBitmap(url, imageView, defaultBmp, 0, 0); } /** * 加载图片-可指定显示图片的高宽 * @param url * @param imageView * @param width * @param height */ public void loadBitmap(String url, ImageView imageView, Bitmap defaultBmp, int width, int height) { imageViews.put(imageView, url); Bitmap bitmap = getBitmapFromCache(url); if (bitmap != null) { //显示缓存图片 imageView.setImageBitmap(bitmap); } else { //加载SD卡中的图片缓存 String filename = FileUtils.getFileName(url); String filepath = imageView.getContext().getFilesDir() + File.separator + filename; File file = new File(filepath); if(file.exists()){ //显示SD卡中的图片缓存 Bitmap bmp = ImageUtils.getBitmap(imageView.getContext(), filename); imageView.setImageBitmap(bmp); }else{ //线程加载网络图片 imageView.setImageBitmap(defaultBmp); queueJob(url, imageView, width, height); } } } /** * 从缓存中获取图片 * @param url */ public Bitmap getBitmapFromCache(String url) { Bitmap bitmap = null; if (cache.containsKey(url)) { bitmap = cache.get(url).get(); } return bitmap; } /** * 从网络中加载图片 * @param url * @param imageView * @param width * @param height */ public void queueJob(final String url, final ImageView imageView, final int width, final int height) { final Handler handler = new Handler() { public void handleMessage(Message msg) { String tag = imageViews.get(imageView); if (tag != null && tag.equals(url)) { if (msg.obj != null) { imageView.setImageBitmap((Bitmap) msg.obj); try { //向SD卡中写入图片缓存 ImageUtils.saveImage(imageView.getContext(), FileUtils.getFileName(url), (Bitmap) msg.obj); } catch (IOException e) { e.printStackTrace(); } } } } }; pool.execute(new Runnable() { public void run() { Message message = Message.obtain(); message.obj = downloadBitmap(url, width, height); handler.sendMessage(message); } }); } /** * 下载图片-可指定显示图片的高宽 * @param url * @param width * @param height */ private Bitmap downloadBitmap(String url, int width, int height) { Bitmap bitmap = null; try { //http加载图片 bitmap = ApiClient.getNetBitmap(url); if(width > 0 && height > 0) { //指定显示图片的高宽 bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true); } //放入缓存 cache.put(url, new SoftReference<Bitmap>(bitmap)); } catch (Exception e) { e.printStackTrace(); } return bitmap; } }
工具类使用
实例化时,可以设置默认的显示图片:
BitmapManager bmpManager = new BitmapManager(BitmapFactory.decodeResource(context.getResources(), R.drawable.loading));
调用加载图片的方法:
bmpManager.loadBitmap(imageURL, imageView);
如果大家有什么疑问的话,欢迎在下面回帖一起探讨。
PS: OSC Android客户端下载地址:
http://www.oschina.net/uploads/osc.apk
OSC iPhone客户端下载地址:
http://www.oschina.net/uploads/osc.ipa
OSC Windows Phone客户端下载地址:
http://www.oschina.net/uploads/osc.xap
转载:http://www.oschina.net/question/157182_59454
发表评论
-
开源中国 4 周年, Android、iPhone、WP7三个平台客户端全面开源
2012-08-31 10:26 10132008年8月31日,OSChina 网站正式上线,到今天刚好 ... -
【OSC手机App技术解析】- 编辑框插入表情图片
2012-08-21 18:36 1282众所周知,APP应用 ... -
【OSC手机App技术解析】- Android完全退出程序
2012-07-23 15:25 747做过Android开发的人都知道,应用程序点击返回键 或者 代 ... -
【OSC手机App技术解析】- 气泡对话列表
2012-07-18 11:47 993在OSC 的Windows Phone以及Andro ... -
【OSC手机App技术解析】- 富文本列表的展示
2012-07-18 11:38 959大家都知道OSC 的网页动态显示是需要多种颜色的才能达到需要 ... -
【OSC手机App技术解析】- 用户通知
2012-07-11 16:31 713大家在使用OSC的手机客户端的过程中,很可能也会收到来自服 ... -
【OSC手机App技术解析】- 集成新浪微博Android SDK
2012-07-10 15:02 1202使用 OSChina.NET Android ... -
【OSC手机App技术解析】- 在WebView中组装HTML
2012-07-10 13:30 1012上一篇我们介绍了 OSChin ... -
【OSC手机App技术解析】- 应用内Web链接的处理
2012-07-08 16:29 732在OSChina.NET手机客户端上显示资讯,最好的方案就是用 ...
相关推荐
Gnome-OSC-HS--2-themes,包含Gnome-OSC-HS-(transparent)和Gnome-OSC-HS-(transparent),用于Ubuntu 18.04,仿mac风格,直接放入/usr/share/themes下就可以了使用
官方离线安装包,亲测可用
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
Gnome-OSC-HS--2-themes.tar.xz ubuntu18.04 仿 mac 主题
《Python库osc-placement详解》 在Python的世界里,丰富的库是其强大功能的重要支撑。本文将深入探讨一个名为"osc-placement"的Python库,版本为1.5.0,它被封装在一个名为"osc-placement-1.5.0.tar.gz"的压缩包中...
OSC振荡器有源无源晶体晶振AD封装库Altium封装库三维视图PCB封装库(3D封装库),52个封装,PcbLibb后缀文件,封装列表如下: Component Count : 52 Component Name ----------------------------------------------- ...
python库。 资源全名:osc-docker-builder-1.7.tar.gz
【标题】"mumu-osc-nicefish-ionic-master_ionic_agou3k_移动端" 指的是一款基于 Ionic 框架开发的移动应用项目,该项目在 "mumu-osc" 开源社区中被创建,并且由 "agou3k" 进行了维护。"nicefish-ionic" 是此项目的...
晶体晶振Altium封装库AD三维视图PCB封装库(2D3D封装库),封装列表如下:Component Count : 38 Component Name ----------------------------------------------- OSC 455E-LI OSC 455E-WI OSC 1612-4P OSC 2025-4...
"mumu-osc-OpenWMS-Frontend-master_back_示范_"这个标题表明这是一个与OpenWMS(开放仓库管理系统)前端相关的项目,可能是某个开发者或团队为了展示后端管理系统的最佳实践而创建的一个备份示例。"back"标签强调了...
【pt-osc在线重建表导致死锁的分析及优化方案】 在进行数据库维护时,特别是在业务低峰期使用像pt-online-schema-change(pt-osc)这样的工具进行在线DDL操作时,可能会遇到死锁问题,这可能导致业务SQL被回滚,...
晶振晶体2D3D封装大全(38个) Component Count : 38 Component Name ----------------------------------------------- OSC 455E-LI OSC 455E-WI OSC 1612-4P OSC 2025-4P OSC 3215-2P ...OSC-3x10-WS
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
晶体晶振3D封装大全PCB库+原理图库(AD集成库,封装带3D视图),Altium Designer的集成封装库,(SchLib+.PcbLib格式的,带3D视图,非常实用。 Component Count : 38 Component Name ...OSC-3x10-WS
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
离线安装包,亲测可用
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
【标题】"osc-android-app2.0改动一下" 指的是开源中国(Open Source China)的Android应用程序的2.0版本进行了一些更新和优化,以便兼容Android Studio 1.3的Preview 2.0版本。这个过程通常涉及到对源代码的修改、...