ListView性能优化——文艺式写法

文章内容为本人手打,理论知识来自eclipse_xu大神在imooc上发布的视频

以下为视频地址:http://www.imooc.com/view/365


ListView是Android开发最常用到的控件之一,也是初学者刚开始接触Android学习会马上碰到的一个控件之一。

学习ListView的性能优化之前,我们首先要了解ListView的缓存机制,简单一句话解释就是----需要时才显示,显示

被回收到缓存区。

下面这张图很好的展示了ListView这种缓存机制


使用ListView我们需要一个数据适配器,什么是数据适配器?简单的说数据适配器就是将我们需要显示到ListView的数据传递给ListView,它起到一个沟通桥梁的作用,具体关系为: 数据---->适配器---->ListView

关于数据适配器在此我们就不做过多的解释,好了,进入今天文章的主题,如何对ListView性能进行优化?

对ListView进行性能优化,本质上是对数据适配器BaseAdapter(or other Adapters)进行优化,

我们先看看我没有对ListView进行优化之前的写法:

public class MyAdapter extends BaseAdapter {

	private ArrayList<Person> mList;
	private LayoutInflater mInflater;

	public MyAdapter(Context context, ArrayList<Person> list) {
		mList = list;
		mInflater = LayoutInflater.from(context);
	}
	
	@Override
	public int getCount() {
		return mList.size();
	}

	@Override
	public Object getItem(int position) {
		return mList.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		
			View view = mInflater.inflate(R.layout.list_item_subject, null);
			
			Person person = (Person) getItem(position);
			
			TextView tv_name = view.findViewById(R.id.tv_name);
			TextView tv_age = view.findViewById(R.id.tv_age);
			TextView tv_sex = view.findViewById(R.id.tv_sex);
			
			tv_name.setText(person.getName());
			tv_age.setText(person.getAge());
			tv_sex.setText(person.getSex());
		
		return view;
	}
	
}

注意观察getView(int position, View convertView, ViewGroup parent)里面的参数,我们发现
position,convertView,parent,三个参数,我们只用到一个position,但却可以显示出我们的效果出来,是不是很神奇?
然而,这不是神奇,反而很逗逼,也许有同学会问为什么啊?效果不是挺好的吗。
我们知道,ListView的每个item都是通过getView函数绘制出来的,也就是说假如你的ListView里面有10项,就要调用getView函数10次,那么我们再来观察getView函数里做了些什么,首先它new出一个view对象出来,找到我们的item布局,接着根据position找到我们的Person实例,接着又new出3个TextView,通过findViewById实例化它们,再为它们setText()。 到这里,聪明的同学就会想到,我们的item布局,3个TextView都是固定的,但是每次getView()都要来View view,TextView tv_XXX,再通过findViewById实例化,是不是存在重复操作了?是不是浪费是CPU资源了?是不是影响性能了?假如我们有100个item那是不是傻逼了?答案是YES,的确存在重复操作了,浪费CPU资源,导致性能下降,那你现在是不是也觉得这种写法很逗比?

下面,我们来解释一种文艺式的写法,这种写法充分利用了getView(int position, View convertView, ViewGroup parent)里面的convertView参数,其原理就是利用listview的缓存机制

package com.nicholasyao.main;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.nicholasyao.models.QListItem;
import com.nicholasyao.models.Subject;
import com.nicholasyao.nijunshuati.R;
import com.nicholasyao.utils.ImageLoader;

public class MyAdapter extends BaseAdapter {

	private ArrayList<Person> mList;
	private LayoutInflater mInflater;

	public MyAdapter(Context context, ArrayList<Person> list) {
		mList = list;
		mInflater = LayoutInflater.from(context);
	}

	@Override
	public int getCount() {
		return mList.size();
	}

	@Override
	public Object getItem(int position) {
		return mList.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {

		ViewHolder viewHolder = null;
		if (convertView == null) {
			viewHolder = new ViewHolder();
			convertView = mInflater.inflate(R.layout.list_item_subject, null);

			viewHolder.tv_name = convertView.findViewById(R.id.tv_name);
			viewHolder.tv_age = convertView.findViewById(R.id.tv_age);
			viewHolder.tv_sex = convertView.findViewById(R.id.tv_sex);

			convertView.setTag(viewHolder);
		} else {
			viewHolder = (ViewHolder) convertView.getTag();
		}

		Person person = (Person) getItem(position);

		viewHolder.tv_name.setText(person.getName());
		viewHolder.tv_age.setText(person.getAge());
		viewHolder.tv_sex.setText(person.getSex());

		return convertView;
	}

	class ViewHolder {
		public TextView tv_name;
		public TextView tv_age;
		public TextView tv_sex;
	}
}


</pre><pre class="java" name="code">
</pre><pre class="java" name="code"><span style="font-family:Microsoft YaHei;"></span>

看看这种文艺式的写法,我们利用到另一个参数convertView,是不是进步了

首先说明一个point , convertView参数是可以被listVie缓存的,也就是说下一次调用getView()函数,convertView里

面该有的东西还存在,知道了这个point后我们来------>看代码

每次调用getView(),我们先判断convertView是不是空的,null的话我们再找item布局,再把3个TextView 通过

FindViewById找出来,然后把这次的结果绑定到convertView上面(通过setTag()),这样做是为了解决我们上面逗

比式写法存在的问题,每次getView()都要各种findViewById,我们现在把第一次findViewById的结果绑定到

convertView上,下次调用getView()判断convertView是不是为空,不是的话直接通过getTag()把我们绑定的东西拿

出来用,所以理论上来说,就算有1000个item,我们实际上只是在第一次getView()的时候findViewById一次,其

他时候都是通过从缓存getTag()拿出来用,比起逗比式写法,这种是不是文艺了很多?性能是不是提升了很多?

如果你问代码中的ViewHolder是什么鬼,请运用你面向对象编程的思维思考一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值