ListView和性能
来源:互联网 发布:电脑桌面归类软件 编辑:程序博客网 时间:2024/06/17 20:52
一谈起ListView,我想大家都不陌生。而且最近该控件特别红,像QQ,人人和新浪客户端里都有它的影子。
其实实现ListView非常的简单。
我想大家都用过各种各样的控件,比如说一个最简单的TextView,我们都是在布局文件里加入TextView标签,然后在Activity里通过findViewById(int id)方法得到该对象的引用,最后调用TextView类的setText(CharSequence s)方法设置该控件的值。
同样,对于ListView,我们先在布局文件里这样添加标签:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ListView android:id="@+id/mylist" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView></LinearLayout>
有了布局文件,然后我们在Activity里通过findViewById(int id)方法得到ListView对象的引用
ListView listView = (ListView) findViewById(R.id.mylist);
有了控件还不行,我们可以把ListView看作是一个可以伸缩的容器,我们需要往里添加内容。作为数据传输的桥梁,Adapter封装了所需的数据,通过调用ListView的方法setAdapter(Adapter a)将数据绑定到ListView中,这样屏幕上就有数据显示了。
Adapter是一个接口,定义了许多规范。Android提供了实现该接口的一些方便的类,如ArrayAdapter,CursorAdapter。下面以ArrayAdapter类为例讲解如何创建一个Adapter。
String[] values = new String[] { "Android", "iPhone", "WindowsMobile", "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2" };// First paramenter - Context// Second parameter - Layout for the row// Third parameter - ID of the TextView to which the data is written// Forth - the Array of dataArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values);
是不是很简单?在上面的那个构造方法中,一共有四个参数,第一个参数很简单,就是一个上下文对象Context,第二个参数是描述每一行的布局,这里使用的是Android自带的一个简单布局,第三个参数是该View的id,最后一个是加入的数组。
上面的ArrayAdapter只能在每一行显示一些文本信息,如果想丰富一下,比如增加图片等,就需要继承该类,实现自己的自定义类。
public class MySimpleArrayAdapter extends ArrayAdapter<String> { private final Context context; private final String[] values; public MySimpleArrayAdapter(Context context, String[] values) { super(context, R.layout.rowlayout, values); this.context = context; this.values = values; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); View rowView = inflater.inflate(R.layout.rowlayout, parent, false); TextView textView = (TextView) rowView.findViewById(R.id.label); ImageView imageView = (ImageView) rowView.findViewById(R.id.icon); textView.setText(values[position]); String s = values[position]; imageView.setImageResource(R.drawable.ok); return rowView; }}
继承该类最关键的就是复写getView()方法,因为ListView是通过该方法得到视图然后显示在屏幕上的。在本方法中,我们自定义了一个XML布局文件,里面有TextView标签和ImageView标签,分别用来显示文字和图片信息,这里是先得到系统服务LayoutInflater,调用该方法的inflate得到该布局的View,最后通过findViewById()方法获取TextView和ImageView的对象引用,再给它们赋值返回就结束了。
但是本章的讨论不是讲解如何实现ListView,但是考虑到有些没有接触过ListView的同志,就大概写了一点demo,同时以此例子为引子,指出该方法存在的一些性能问题。
由于通过调用LayoutInflater的inflate方法获得的View,其实会产生新的对象,创建对象是很耗时和资源的(内存),另外调用getViewById()方法也会相对耗时和耗资源,虽然其强度不如前者。
所以Android决定,如果代表每一行的View不可见(向下滑动,上面的View被遮住了,即为不可见),那么它将允许getView方法通过convertView复用该View,达到提升性能的目的。
我们先来看下ArrayAdapter是如何进行优化的。
public View getView(int position, View convertView, ViewGroup parent) { return createViewFromResource(position, convertView, parent, mResource); } private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) { View view; TextView text; if (convertView == null) { view = mInflater.inflate(resource, parent, false); } else { view = convertView; } try { if (mFieldId == 0) { // If no custom field is assigned, assume the whole resource is a TextView text = (TextView) view; } else { // Otherwise, find the TextView field within the layout text = (TextView) view.findViewById(mFieldId); } } catch (ClassCastException e) { Log.e("ArrayAdapter", "You must supply a resource ID for a TextView"); throw new IllegalStateException( "ArrayAdapter requires the resource ID to be a TextView", e); } T item = getItem(position); if (item instanceof CharSequence) { text.setText((CharSequence)item); } else { text.setText(item.toString()); } return view; }
该方法首先判断传给该方法的convertView是否为null,如果为null,那么就调用耗时的inflate方法创建View对象,如果不为空(该convertView是以前inflate过的,只不过被遮住了),就复用该对象,达到了部分优化。
上面之所以说是部分优化,是因为只考虑了优化inflate带来的负载,而忽略了getViewById()方法引起的性能问题。解决办法是在自定义Adapter类里引进静态内部类ViewHolder,如其名字,该类里存放我们需要显示每一行的所有控件,比如TextView,ImageView等。当convertView为空时,我们创建布局文件的View,然后分别得到布局里的各种控件,再把它们存放在ViewHolder类里,最后再调用convertView的 setTag(Object o)方法把该类绑定到该类里。
public class MyPerformanceArrayAdapter extends ArrayAdapter<String> { private final Activity context; private final String[] names; static class ViewHolder { public TextView text; public ImageView image; } public MyPerformanceArrayAdapter(Activity context, String[] names) { super(context, R.layout.rowlayout, names); this.context = context; this.names = names; } @Override public View getView(int position, View convertView, ViewGroup parent) { View rowView = convertView; if (rowView == null) { LayoutInflater inflater = context.getLayoutInflater(); rowView = inflater.inflate(R.layout.rowlayout, null); ViewHolder viewHolder = new ViewHolder(); viewHolder.text = (TextView) rowView.findViewById(R.id.TextView01); viewHolder.image = (ImageView) rowView .findViewById(R.id.ImageView01); rowView.setTag(viewHolder); } ViewHolder holder = (ViewHolder) rowView.getTag(); String s = names[position]; holder.text.setText(s); if (s.startsWith("Windows7") || s.startsWith("iPhone") || s.startsWith("Solaris")) { holder.image.setImageResource(R.drawable.no); } else { holder.image.setImageResource(R.drawable.ok); } return rowView; }}
根据统计信息,这样的优化设计,比最初的方法效率上要快15%以上。
Over...
- ListView和性能
- ListView和DataGridView性能比较
- RecyclerView 和 ListView 性能和效果区别
- ListView的简单使用和性能优化
- ListView数据显示重复和性能问题
- ListView性能优化之convertView和ViewHolder
- ListView的性能优化-convertView和viewHolder
- ListView性能
- ListView性能
- ListView和RecyclerView的使用和性能优化总结
- ListView的性能优化之convertView和viewHolder
- ListView的性能优化之convertView和viewHolder
- ListView的性能优化之convertView和viewHolder
- ListView的性能优化之convertView和viewHolder
- ListView的性能优化之convertView和viewHolder
- ListView的性能优化之convertView和viewHolder
- ListView的性能优化之convertView和viewHolder
- ListView的性能优化之convertView和viewHolder
- 星号图函数调用
- 关于赋值运算符函数
- Android手机主流屏幕分辨率有哪些?
- 2012-11-16 hibernate锁、hql联接查询、where子句中的boolean条件
- 禁用图片等提高FirefoxDriver的加载速度
- ListView和性能
- 一维子数组最大和
- 光棍节那天 IT男的表白程序
- 软件腐化
- QT读写ini文件
- 用程序解密爱因斯坦经典难题
- 【STL】C++语言ctime库
- 机器学习 数据挖掘 资料包
- 国内顶尖网页游戏制作人和主策划名单