- 浏览: 514740 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
u010169720:
而且fragment调用back也有不需要finish的时候呢 ...
android异常:Can not perform this action after onSaveInstanc -
u010169720:
我这里就是拦截的,但是还是报了这个
android异常:Can not perform this action after onSaveInstanc -
Salijing:
IT之冕 写道 我的方法是注释掉super.onBackPre ...
android异常:Can not perform this action after onSaveInstanc -
cainiao1923:
上线毛啊,Bad request了
基于NodeJs开发的独立博客系统~~上线啦 -
cainiao1923:
不错 !!!!!!!!!!!!!!
在Android上实现Java和Js交互
探秘ListView的ConvertView以及ViewHolder原理
- 博客分类:
- Android那些事儿
最近在使用android的组件ExpandableListView,实现需求时,遇到不少奇怪的问题。
我的需求就是在ExpandableListView的父一级的view上添加两个按钮,实现添加子一级view的添加一级删除自己的功能。
自定义的layout如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout_parentView" android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/iv_flag" android:layout_width="10dp" android:layout_height="10dp" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_marginLeft="5dp" android:focusable="false" /> <TextView android:id="@+id/tv_typename" android:layout_width="100dp" android:layout_height="30dp" android:layout_centerInParent="true" android:layout_marginLeft="10dp" android:focusable="false" /> <ImageButton android:id="@+id/iv_dele" android:layout_width="40dp" android:layout_height="40dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="5dp" android:src="@drawable/del" android:focusable="false"/> <ImageButton android:id="@+id/iv_add" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginRight="10dp" android:layout_toLeftOf="@id/iv_dele" android:src="@drawable/add" android:focusable="false"/> </RelativeLayout>
GroupView部分的Java代码如下:
@Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { View parentView = null; if(groupViews.size()>groupPosition){ parentView = groupViews.get(groupPosition); } else { parentView = newParentView(groupPosition); groupViews.add(parentView); } return parentView; } private View newParentView(int groupPosition){ View parentView = li_parent.inflate(R.layout.list_parent_view, null); TextView textview = (TextView) parentView.findViewById(R.id.tv_typename); BigType bt = groupList.get(groupPosition); textview.setText(bt.getName()); View v_dele = parentView.findViewById(R.id.iv_dele); v_dele.setTag(bt.getName()); v_dele.setOnClickListener(new BtnDeleBigTypeListener(ct)); View v_add = parentView.findViewById(R.id.iv_add); v_add.setTag(bt.getName()); v_add.setOnClickListener(new BtnAddSmallTypeListener(ct)); return parentView; }
当Activity加载该layout后,当没有展开子一级,父一级上的两个ImageButton按钮均点击正常,可是当点开子一级后,点击两个ImageButton,均得不到立即的响应, 非得再产生了其他控件的点击事件(例如点击父一级,让其收起)后,之前点击 ImageButton的事件才会得到响应。一开始感觉是事件响应队列阻塞,可是为啥在产生新的事件后,所有的事件又会马上得到响应呢?
先做一个测试,代码见下,代码里的ViewHolder是一个自定义的类,也是后面ViewHolder模式的主要体现,这里先卖一关子...
View cache = null; @Override public View getGroupView(int groupPosition, boolean isExpanded,View convertView, ViewGroup parent) { ViewHolder _vh = null; if(convertView == null){ _vh = new ViewHolder(); convertView = newParentView(_vh); convertView.setTag(_vh); cache = convertView; } else { _vh = (ViewHolder) convertView.getTag(); if(cache.equals(convertView)){ Log.i(TAG, "equals old obj"); } } return convertView; }
上面代码主要就是想测试converView,究竟是拿来干什么的,google文档里头做了如此解析:
大致意思就是在重复利用此物之前要检查其是否为null!可是就没说清楚,这个convertView究竟是什么时候会存在!
现在来看看测试的结果,ExpandableListView总共有4个父节点,但是有以下三次输出结果:
这表明,ExpandableListView每次都在重画通过getGroupView拿到的View,而且只创建一次,之后都是都是同一个!这下子明白了,前面不能响应的按钮点击事件,原来是convertView这一覆盖层在搞鬼!因为我在代码里头每次都是在newPareView的,结果原来的convertView还在,结果就盖住了新的view,导致事件流分派出现问题,当再有convertView以外的事件发生,或ExpandableListView刷新,事件流恢复正常,响应也就正常了...
看来有时候真的要好好研究理解清楚API更深层次的用意才好做开发 啊!
不过话又说回来,其实ExpandableListView(包括ListView)的这个convertView是很有用的,因为ExpandableListView只是根据getGroupView返回的view去画列表,但是一般list列表的内容在同一级基本都会有共通性,只是加载的信息内容不同,所以重用convertView,可以很大程度上提升ListView的性能,特别是在加载大数据量时。这里配合ViewHolder模式,就可以更好地对久对象进行重用了!
下面是改良过得代码:
@Override public View getGroupView(int groupPosition, boolean isExpanded,View convertView, ViewGroup parent) { ViewHolder _vh = null; if(convertView == null){ _vh = new ViewHolder(); convertView = newParentView(_vh); convertView.setTag(_vh); } else { _vh = (ViewHolder) convertView.getTag(); } BigType bt = groupList.get(groupPosition); String name = bt.getName(); _vh.getTitle().setText(name); ImageButton _btn_dele = _vh.getBtn_dele(); _btn_dele.setTag(name); _btn_dele.setFocusable(false); _btn_dele.setClickable(true); _btn_dele.setOnClickListener(new BtnDeleBigTypeListener(ct)); ImageButton _btn_add = _vh.getBtn_add(); _btn_add.setTag(bt.getName()); _btn_add.setFocusable(false); _btn_add.setClickable(true); _btn_add.setOnClickListener(new BtnAddSmallTypeListener(ct)); return convertView; } private View newParentView(ViewHolder vh){ View parentView = li_parent.inflate(R.layout.list_parent_view, null); ImageView iv_flag = (ImageView)parentView.findViewById(R.id.iv_flag); vh.setImg_flag(iv_flag); TextView tv = (TextView) parentView.findViewById(R.id.tv_typename); vh.setTitle(tv); ImageButton btn_dele = (ImageButton) parentView.findViewById(R.id.iv_dele); vh.setBtn_dele(btn_dele); ImageButton btn_add = (ImageButton) parentView.findViewById(R.id.iv_add); vh.setBtn_add(btn_add); return parentView; }
其实ViewHolder并不是什么神奇的工具,他只是一个简单的vo,保存着父一级view上个控件的应用,方便在重用时,加载新的内容而已。
class ViewHolder { private TextView title; private ImageView img_flag; private ImageButton btn_add; private ImageButton btn_dele; public TextView getTitle() { return title; } public void setTitle(TextView title) { this.title = title; } public ImageView getImg_flag() { return img_flag; } public void setImg_flag(ImageView img_flag) { this.img_flag = img_flag; } public ImageButton getBtn_add() { return btn_add; } public void setBtn_add(ImageButton btn_add) { this.btn_add = btn_add; } public ImageButton getBtn_dele() { return btn_dele; } public void setBtn_dele(ImageButton btn_dele) { this.btn_dele = btn_dele; } }
发表评论
-
【翻译】 Android上实现文字围绕图片的布局
2014-04-09 16:31 3419在这边文章中,我将会介绍如何去实现一个在An ... -
【翻译】Android多线程下安全访问数据库
2014-04-08 11:21 11480为了记录如何线程安全地访问你的Android数 ... -
Android Robotium小结
2014-03-17 15:41 2342Robotium 是一款基于Android instrum ... -
Monkeyrunner小结
2014-03-15 23:49 6539Monkeyrunner----Android tools ... -
Android开发陷阱:利用PendingIntent传递唯一的Intent
2013-11-07 11:36 42141PendingIntent 是对真实 ... -
Android开发陷阱:利用PendingIntent传递唯一的Intent
2013-11-07 11:29 0PendingIntent 是对真实 ... -
GridView的特殊派生应用
2013-11-06 17:07 2151一、ScrollView + GridView 在Sc ... -
Android的ps命令介绍和技巧
2013-07-05 18:37 6664在Linux下,ps是非常普 ... -
在Android上实现Java和Js交互
2013-07-05 18:34 28262其实webview加载资源的速度并不慢,但是如果资源多 ... -
TextView的日常使用技巧
2013-07-05 18:29 5043Textview在日常开发工作中使用非常频繁,在这里 ... -
Android NDK开发之Jni调用Java对象
2013-03-16 00:11 26430本地代码中使用Java对 ... -
Android NDK开发之数组类型的操作
2013-03-16 00:05 8840Jni 可以通过JNIEnv提供的方法,对传过来的Java ... -
Android NDK开发之Jni的数据类型
2013-03-16 00:03 11393在前面的一篇博客《And ... -
Android NDK开发简介
2013-03-07 15:12 5914最近由于项目的 ... -
Android的NDK开发~SQLite3
2013-02-05 14:02 0What? NDK的N,即native,NDK开发,是指使 ... -
Android的NDK开发~Hellow world!
2013-02-05 13:52 24541、到Google官网下载adt- ... -
关于SD卡管理的注意事项
2013-01-18 11:24 11901问题: 本人一直有使 ... -
Activity流程控制之startActivityForResult
2012-10-18 09:48 0startActivityForResult不能与flag I ... -
Json解析之Gson库
2012-09-24 11:46 25572Json(JavaScript Object Notation ... -
搞定个性化输入提示--自定义AutoCompleteTextView
2012-09-04 14:44 5059在设计app的输入界面时,假如假如智能提示,给用户带来的不只是 ...
相关推荐
通过这个例子,你可以学习如何创建自定义的ListViewAdapter,理解ViewHolder的工作原理,并将其应用于实际项目中。同时,也可以尝试扩展这个适配器,例如添加点击事件监听、支持不同类型的列表项等,以适应更复杂的...
本资源包含了一个关于ListViewAdapter和ViewHolder的代码示例,帮助开发者更好地理解和实现这个功能。 **ListViewAdapter详解** ListViewAdapter是Android SDK提供的一个抽象类,它是BaseAdapter的子类。开发者需要...
"ListView使用ViewHolder模式提高效率"这一主题就是解决这个问题的关键知识点。 ViewHolder模式是Android开发中为了提升ListView性能而设计的一种优化策略。它通过减少findViewById的调用来改善视图的绘制速度。在...
本篇将深入探讨如何通过抽取ViewHolder和优化Adapter来提升ListView的性能。 ViewHolder模式是解决ListView滚动卡顿的关键。在ListView的onCreateViewHolder和onBindViewHolder方法中,ViewHolder充当了一个缓存的...
为了提高ListView的性能和用户体验,开发者通常会采用`ViewHolder`模式和自定义`Adapter`,如`CommonAdapter`。本文将深入探讨如何利用这两种技术打造一个万能的ListView适配器。 首先,`ViewHolder`模式是优化...
- 在getView()方法中,首先根据position获取ViewHolder对象,如果convertView的Tag没有ViewHolder,就创建一个新的ViewHolder并将其设置为convertView的Tag。 - 然后,根据数据源中的数据填充ViewHolder中的组件,...
在Android开发中,ListView是一种常见的组件,用于展示大量的...开发者应熟练掌握convertView的使用,以及结合ViewHolder和多布局策略来优化ListView的性能。在实际开发中,合理运用这些技巧,可以显著提升用户体验。
本文将深入探讨ListView的BaseAdapter用法,以及如何利用convertView与ViewHolder优化性能。 一、ListView基础 ListView是Android提供的一个可以显示大量数据的滚动视图,通过动态加载的方式,只显示当前可视区域...
首先,我们需要理解ListView的工作原理。ListView通过ViewHolder模式优化性能,复用已创建的列表项视图(View)。这意味着当用户滚动列表时,已显示过的视图会被重新使用,因此我们需要确保在每个视图被重新显示时...
这个类可能包含了创建ViewHolder的方法,以及处理数据绑定和视图复用的逻辑。通过这种方式,无论数据类型如何变化,Adapter都能够灵活应对,同时保证列表的高性能和良好的用户体验。 总之,通用Adapter和ViewHolder...
本篇文章将深入探讨ListView的基本用法,数据源的添加,以及优化性能的ViewHolder机制。 首先,ListView的基础使用主要包括以下几个步骤: 1. **布局文件**:在XML布局文件中,我们需要创建一个ListView标签,并为...
- 为了提高ListView的滚动性能,通常会在`getView()`方法中使用convertView和ViewHolder模式。ViewHolder持有列表项中各个控件的引用,避免频繁的findViewById操作。 4. **Switch的使用**: - Switch是Android的...
本篇将详细讲解ViewHolder的超级简洁写法,以及如何通过这个设计模式优化ListView的性能。 ViewHolder模式的核心思想是减少findViewById()的调用,因为这个方法在执行时会进行大量的查找操作,消耗时间。通过复用已...
使用了convertView和viewHolder两种优化方式,ListView的子布局是单一布局,对应的我的博客地址是: http://blog.csdn.net/u012320459/article/details/47667869
Android ListView多种布局优化demo,使用了两种优化手段,包括convertView,ViewHolder,对应的我的博客地址是: http://blog.csdn.net/u012320459/article/details/47667869
我们在使用ListView的时候,经常会使用的ViewHolder方式作为缓存,每次都需要手动的通过viewholder.icon = convertview.findVIewByid(id);一般的app都会有好几个页面会用到ListView,这样的话我们的代码量就会很大,...
为了测试ListView的工作原理,我们可以创建一个简单的应用,包含一个ListView,以及一个自定义Adapter。Adapter的数据源可以是一个数组或者数据库查询的结果。然后在`getView()`方法中,模拟数据填充和视图复用的...
本篇文章将深入探讨ListView与BaseAdapter的工作原理,并详细介绍如何进行性能优化。 首先,我们来理解一下Adapter在Android中的作用。Adapter是连接数据源和UI组件的桥梁,它负责将数据转化为可显示的视图。在...
2. ViewHolder模式:利用convertView和ViewHolder,减少视图的创建和查找,提高列表滑动的流畅性。 3. 列表项复用:避免不必要的对象创建,比如在getView()方法中,通过判断convertView是否为空来重用已存在的视图。...
在Android开发中,ViewHolder模式是优化ListView性能的关键技术之一,特别是在处理大数据量列表时,能够显著提升滚动流畅性。本文将深入探讨ViewHolder的应用及其在ListView和Adapter中的作用。 首先,我们来理解...