您的位置:首页 > 移动开发 > Android开发

Android性能优化 (一)- ListView

2015-03-31 11:33 302 查看

一、概述

这里对ListView进行性能的优化,是指在对adapter进行重写的时候,需要注意影响ListView性能的地方。

ListView包含的三要素:

1.ListView : 用于显示列表的view;

2.adapter: 用于将数据映射到listview的容器;

3.data: 具体需要被映射的数据(包括 字符串、图片或其他的控件等)

二、优化原理

由此,优化Listview的性能,就围绕这三要素:

优化1:只创建必要的view对象;

这个是从加载数据的方式上进行的优化:

在未做优化前,大概的过程是:首先调用getCount()函数,返回值即为listView的数据长度,然后根据这个长度,再调用getView(int position, View convertView, ViewGroup parent)的方法获取每个Item所对应的view,在getView(int position, View convertView, ViewGroup parent)函数中,会对每个Item都创建一个对象,这样必然会占用很多的内存,影响效率了。

优化2:尽可能减少Layout的inflate的操作;

inflate操作是利用xml文件实例化从而生成相应的View对象的,因为涉及到XML文件的读取,属于IO操作,每次创建item的view时,都会涉及读取一次,影响效率了。

优化3:尽可能较少findViewById();

通过findViewById()方法可以在一个xml文件中找到相应的view,但是这个方法本质上会递归整个view树,以寻找与id相匹配的view,当每个item中的布局比较复杂时,频繁地调用findViewById()肯定也是会影响效率了。

三、优化机制

1.Recycler (针对优化1 和优化2)

当ListView中item离开当前视图时,对应的view则会被缓存在Recycler中。此时,相应地从下方生成一个item,此时调用getView(int position, View convertView, ViewGroup parent)函数时,其中传入的convertView便是缓存在Recycler中的view。所以,针对这方面的优化关键在于如何重用convertView!

这样优化,可以避免重复根据xml创建view对象,有效减少xml文件的IO和view的频繁创建。

2.viewHolder静态类(针对优化3)

将item中元素的对象封装成一个自定义的类,然后通过convertView的setTag(Object object)函数将其中成员和xml中的控件绑定在一起,只要对应的convertView还在,那么其相应的Tag就还在,从而通过取viewHoler类成员的方式获取控件,避免每次的findViewById(),另外,因为viewHolder与外部类之间并没有需求相互访问变量或者其他实体,所以最好声明成static静态类。

四、具体实现:

最初的写法:

public View getView(int position, View convertView, ViewGroup parent) {
View view = LayoutInflater.from(mContext).inflate(R.layout.listview_item, null);
ImageView imageView1 = (ImageView)view.findViewById(R.id.imageView1);
TextView textView2 = (TextView)view.findViewById(R.id.text2);
imageView1.setImageResource(R.drawable.ic_launcher);
textView2.setText(mData.get(position));
return view;
}


修改后的写法:

static class ViewHolder{
//静态类,并将其对象设置进convertView中,避免每次findViewById()
ImageView imageView1;
TextView textView1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;

if(convertView == null){//重用convertView,避免每次都给item创建View
holder = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(R.layout.listview_item, null);
holder.imageView1 = (ImageView)convertView.findViewById(R.id.imageView1);
holder.textView1 = (TextView)convertView.findViewById(R.id.text1);
convertView.setTag(holder);
}else{
//只要convertView还在Recycler中,那么其对应的Tag,也即viewHolder对象就在
holder = (ViewHolder)convertView.getTag();
}

holder.imageView1.setImageResource(R.drawable.ic_launcher);
holder.textView1.setText(mData.get(position));

return convertView;
}


最后,其实也可以通过注入框架来精简代码:

static class ViewHolder{
@InjectView(R.id.imageView1)
ImageView imageView1;
@InjectView (R.id.text1)
TextView textView1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;

if(convertView == null){
holder = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(R.layout.listview_item, null);
convertView.setTag(holder);
}else{
holder = (ViewHolder)convertView.getTag();
}

holder.imageView1.setImageResource(R.drawable.ic_launcher);
holder.textView1.setText(mData.get(position));

return convertView;
}


其实到这里,还不算完,需要特别注意,在item中包含大量图片的时候,就需要针对图片做优化了,这个嘛,在另外的博客里继续说道。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: