Android之ListView/GridView 优化
一、效率最低的getView实现
我们知道,ListView和GridView的显示都是通过Adapter的getView实现的。
ListView/GridView数据量较小时,我们的处理方式一般是这样的(效率最低的一种方式)
1 public View getView(int position, View convertView, ViewGroup parent) { 2 View item = mInflater.inflate(R.layout.list_item_icon_text, null); 3 ((TextView) item.findViewById(R.id.text)).setText(DATA[position]); 4 ((ImageView) item.findViewById(R.id.icon)).setImageBitmap( 5 (position & 1) == 1 ? mIcon1 : mIcon2); 6 return item; 7 }
当数据量非常大时,这样每一次getView都会去inflate布局,效率太差,这会让我们的程序卡顿,滑动多了还会OOM。
二、利用Android已经提供了View缓存机制实现ViewHolder模式——实现View共享
我们注意到getView的第二个参数convertView,这个是View缓存机制的关键。简单的说就两点:
1.假设当前页面我们有7个item,那么前七次getView,这个convertView一开始都是null。因此我们需要inflate布局,这样我们得到7个convertView(convertView1——converView7)
2.假设我们往上翻页,现在Item8进入页面,item1出页面,此时Item8对应的getView中的convertView就是convertView1。
利用这个View缓存机制的特点,我们只需要将Item8的getView中convertView(即convertView1)的数据由item1更新为item8即可。也就是说item8和item1就实现了View的共享(共享convertView1)。(本来嘛,item8和item1永远不会在一个界面中一起出现,确实应该共享一些资源)
而这就是所谓的ViewHolder模式
@Overridepublic View getView(int position, View convertView, ViewGroup arg2) {ListLog.i("xerrard", "getView " + position + " " + convertView);ViewHolder viewHolder = null;if(convertView == null){viewHolder = new ViewHolder();convertView = inflater.inflate(R.layout.item, null);viewHolder.image = (ImageView) convertView.findViewById(R.id.img);viewHolder.text = (TextView) convertView.findViewById(R.id.txt);convertView.setTag(viewHolder);}else{viewHolder = (ViewHolder) convertView.getTag();}viewHolder.image.setImageBitmap(imgs.get(position));viewHolder.text.setText(texts.get(position));return convertView;}class ViewHolder{ImageView image;TextView text;}
三、ListView /GridView的异步加载。
很多时候我们会需要再网上下载一些图片来进行显示,如果在主线程做下载的操作,这样很可能会造成ANR,所以需要子线程来实现。(即使是本地存储中的图片,也建议用子线程来实现,本地IO操作有时也会造成ANR)
我们使用android中的AsyncTask来实现下载的操作
1 /** 2 * Created by xuqiang on 15-12-16. 3 */ 4 public class ImageTask extends AsyncTask<String, Void, Bitmap> { 5 private ImageView iv; 6 String imgUrl; 7 public ImageTask(ImageView iv){ 8 this.iv = iv; 9 } 10 11 @Override 12 protected Bitmap doInBackground(String... param) { 13 imgUrl = param[0]; 14 try { 15 URL url = new URL(imgUrl); 16 try { 17 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 18 InputStream in = conn.getInputStream(); 19 Bitmap bitmap = BitmapFactory.decodeStream(in); 20 if(bitmap!=null){ 21 return bitmap; 22 } 23 } catch (IOException e) { 24 // TODO Auto-generated catch block 25 e.printStackTrace(); 26 } 27 } catch (MalformedURLException e) { 28 // TODO Auto-generated catch block 29 e.printStackTrace(); 30 } 31 return null; 32 } 33 34 @Override 35 protected void onPostExecute(Bitmap result) { 36 super.onPostExecute(result); 37 if (result != null) { 38 // 通过 tag 来防止图片错位 39 if (iv.getTag() != null && iv.getTag().equals(imgUrl)) { 40 iv.setImageBitmap(result); 41 } 42 } 43 } 44 45 @Override 46 protected void onPreExecute() { 47 super.onPreExecute(); 48 } 49 }
然后在getView中,我们只需要将原本对ViewHolder的操作,传参数给ImageTask来处理
ImageTask imageTask = new ImageTask(viewHolder.image,position);imageTask.execute(imgUrls.get(position));
四、ListView /GridView的异步加载中的错位问题解决
刚才我们知道,利用的android的View缓存机制,我们可以使用ViewHolder优化ListView/GridView的效率。但是在异步加载图片的过程中,正是因为这个View共享的机制,会造成图片错位的情况。
——当快速滑动的情况下,会出现item1和item8都显示部分的情况。
a.item1和item8共享一个convertView,而异步加载的情况下,是有可能会出现item8异步加载完毕准备显示时,item1还没有加载完毕,这样就会出现先convertView.setView(item8),然后convertView.setView(item1),这样原本应该显示item8的位置却显示了item1。
b.即使是先加载完Item1,再加载完Item8,也会给用户一种原本应该显示item8的地方先显示item1后再正常显示item8的感觉。
这个问题,我们如何解决。
最简单的解决方法就是网上说的,给 ImageView 设置一个 tag。
当 Item1 比 Item8 图片下载的快时, 你滚下去使 Item8 可见,这时 ImageView 的 tag 被设成了
Item8 的 URL, 当 Item1 下载完时,由于 Item1 不可见现在的 tag 是 Item8 的 URL,所以不满足条件,
虽然下载下来了但不会设置到 ImageView 上, tag 标识的永远是可见 view 中图片的 URL。
我们最后将这个最终的改进方案写下来
1.在主线程设置一个tag,
1 @Override 2 public View getView(int position, View convertView, ViewGroup arg2) { 3 Log.i("xerrard", "getView " + position + " " + convertView); 4 ViewHolder viewHolder = null; 5 if(convertView == null){ 6 viewHolder = new ViewHolder(); 7 convertView = inflater.inflate(R.layout.item, null); 8 viewHolder.image = (ImageView) convertView.findViewById(R.id.img); 9 10 convertView.setTag(viewHolder); 11 }else{ 12 viewHolder = (ViewHolder) convertView.getTag(); 13 } 14 viewHolder.image.setTag(imgUrls.get(position)); 15 ImageTask imageTask = new ImageTask(viewHolder.image); 16 imageTask.execute(imgUrls.get(position)); 17 return convertView; 18 } 19 class ViewHolder{ 20 ImageView image; 21 } 22 }
2.在异步的ImageTask设置图片的地方,判断Tag,确认Tag没有问题之后,再设置图片
1 @Override 2 protected void onPostExecute(Bitmap result) { 3 super.onPostExecute(result); 4 if (result != null) { 5 // 通过 tag 来防止图片错位 6 if (iv.getTag() != null && iv.getTag().equals(imgUrl)) { 7 iv.setImageBitmap(result); 8 } 9 } 10 }
转载于:https://www.cnblogs.com/xerrard/p/5052734.html
Android之ListView/GridView 优化相关推荐
- ym——Android之ListView性能优化
转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持! Android之ListView性能优化 假设有看过我写过的15k面试题的朋友们一定知 ...
- Android 使用Listview的优化
Listview是Android中很重要的一个组件,在开发过程中使用到的Listview能站到30%,在新手开发过程中,往往会忽略对Listview的优化,在上一个项目的开发中,确实用到了很多List ...
- Android中ListView数据处理优化
来自:OPEN经验库 原帖:http://www.open-open.com/lib/view/open1330132229874.html Android 应用开发中,采用ListView组件来展示 ...
- Android中ListView的优化
ListView的优化方案有很多,主要是以下几点 1. 重用了convertView,减少了内存消耗.通过判断convertView是否为null,是的话就需要产生一个ViewHol ...
- Android Studio ListView框架+优化安卓应用市场实例
直接使用ListView的基本步骤 获取数据 创建适配器 绑定适配器 需要实现重写的函数: getCount() 获取数据长度 getItem (int position) 获取项资源 getItem ...
- android中Listview的优化技巧
2019独角兽企业重金招聘Python工程师标准>>> 减少内存中view对象的创建个数(明显提高效率) 复用历史缓存的view对象,减少Android内存消耗 减少子孩 ...
- Android ListView性能优化实例讲解
前言: 对于ListView,大家绝对都不会陌生,只要是做过Android开发的人,哪有不用ListView的呢? 只要是用过ListView的人,哪有不关心对它性能优化的呢? 关于如何对ListVi ...
- Android PullToRefresh (ListView GridView 下拉刷新) 使用详解
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38238749,本文出自:[张鸿洋的博客] 群里一哥们今天聊天偶然提到这个git ...
- Android在ListView中嵌套一个GridView时只显示一行的原因及解决方法
在之前的编程里,我还没有遇到过要在一个ListView中嵌套一个GridView或是在一个GridView中嵌套一个ListView.所以今天事儿来了!我花了一将近3个小时,找到了为什么我在一个Lis ...
- Android之ListView原理学习与优化总结
在整理前几篇文章的时候有朋友提出写一下ListView的性能优化方面的东西,这个问题也是小马在面试过程中被别人问到的-..今天小马就借此机会来整理下,网上类似的资料蛮多的,倒不如自己写一篇,记录在这个 ...
最新文章
- 创建Swap交换空间
- 中国、意大利等国研究员用AI 发现新的月球陨石坑 | AI日报
- Acwing第 41 场周赛【完结】
- nyoj117求逆序数 并归排序法
- Linux网络编程服务器模型选择之并发服务器(下)
- JAVA---事件适配器----用内部类,匿名类实现事件处理
- Android数据存储之SQLite数据库存储
- RedHat红帽RHEL7安装与使用,VMware Workstation16 Pro虚拟机的安装与使用
- java学生管理系统登录注册_Java程序---学生管理系统的登录和注册
- 微信小程序java python node医疗微服务系统医院预约挂号系统
- 【OpenCV-Python】教程:5-3 光流
- IoT开发——WIFI模块ESP8266 RTOS SDK V3.0.0环境搭建
- VUE 首屏加载时间优化
- 通过Charmed Ceph 在 H3C UniServer R4950 G5 服务器上 部署独立的Ubuntu Ceph 存储集群
- 白鹭引擎王泽:重度H5游戏性能优化技巧标题的文章
- 使用IText7 生成PDF文档
- 麦肯锡三部曲_人际连接三部曲
- IdentityServer4实战详解
- mw325r 服务器无响应),水星(MERCURY)MW325R路由器连不上网怎么办?
- 边沿捕获寄存器-Verilog
热门文章
- 客户端登陆服务器用户名验证
- ./configure: error: the HTTP rewrite module requires the PCRE library.
- Hadoop2.2.0中HDFS的高可用性实现原理
- Autodesk Map 3D 2012 新功能介绍
- Linux 基本网络配置
- 专注于钢铁行业电子商务的服务网站,钢铁行业的网上贸易市场 一起成长
- SecureCRT的logon action登录跳转设置
- linux关于bashrc与profile的区别(转)
- Spring Cloud 2020 年路线图
- Linux 正在吞噬 Windows 和 Chrome OS!