Android之listview优化+分类显示

今天就来说说ListView这个组件吧,这个组件相信每个App都会涉及到~当然或许很多人已经知道 ListView 的优化。在这里我在详细的说一下listview的优化,顺便让ListView分类显示~~让效果更好~

先来看效果图:


从这个图中可以看出,可以看到数据有100个(0-99),奇数和偶数分类显示,并给每类数据加了一个头~显示是奇数还是偶数的。

步骤:

1.在activity_main布局中编写listview组件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.listview.MainActivity" >

    <ListView 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/listview"></ListView>

</RelativeLayout>
2.在MainActivity里为listview设置适配器

        private ListView listview;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		listview=(ListView) findViewById(R.id.listview);
		listview.setAdapter(new MyAdapter());
	}
3.ListView设置数据,这里就使用模拟数据(0-99),并把数据分成两类(奇数和偶数)

	private List<String>jiData;//奇数
	private List<String>ouData;//偶数
        jiData=new ArrayList<String>();
	ouData=new ArrayList<String>();
	for(int i=1;i<=100;i++){
		if(i%2==0)
			ouData.add(i+"");
		else
			   jiData.add(i+"");
	}
4.然后要为MyAdapter继承BaseAdapter,实现4个方法~

(1)public int getCount() {}     代表的是返回listView有多少个条目

(2)public Object getItem(int position) {}  指的是返回位置为position的条目

(3)public long getItemId(int position) {}  指的是返回位置为position的条目的Id

(4)public View getView(int position, View convertView, ViewGroup parent) {} 指的是返回每个条目的视图

我们最重要的是第4个方法-getView方法,前面几个这样写:

		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return 1+jiData.size()+1+ouData.size();
		}

		@Override
		public Object getItem(int position) {
			// TODO Auto-generated method stub
			//俩者效果一样
			return null;
			//return data.get(position);
		}

		@Override
		public long getItemId(int position) {
			// TODO Auto-generated method stub
			return position;
		}
现在来看看getView方法,在这个方法里我们要对listview优化和分类显示,所以代码量有点多~

先来分析一下一点都不优化的方式-逗比式

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			// TODO Auto-generated method stub
			/*LayoutInflater layoutInflater=LayoutInflater.from(MainActivity.this);
			View view=layoutInflater.inflate(R.layout.listview, null);*/
			//不优化,逗比式
			System.out.println(convertView);
			View view=View.inflate(MainActivity.this, R.layout.listview, null);
			TextView tv=(TextView)view.findViewById(R.id.tv);
			text=data.get(position);
			tv.setText(text);
			return view;
		}

我们知道getView的调用次数,是有多少个条目就调用多少次吧,那么上面这么写的加载布局和findViewById就会调用100次吧,而每个条目的布局都一样,为什么要重复加载呢,所以要想办法减少加载布局的次数,这样更优化,那该怎么做呢。

我们可以看到getView方法有三个参数,第二个参数convertView还没有使用到,对,有人应该知道就是缓存。

convertView工作原理:


这里屏幕只显示8个条目,你的可能不是,因为每个手机的屏幕大小不一样嘛,不过原理都是一样的。

看到这里我们知道了convertView,所以接下来可以使用convertView来减少加载布局的次数:

那就是所谓的普通式

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			// TODO Auto-generated method stub
			/*LayoutInflater layoutInflater=LayoutInflater.from(MainActivity.this);
			View view=layoutInflater.inflate(R.layout.listview, null);*/	
			
			//普通式,虽然对视图进行了优化,不用每次都重新加载,但是每次都要findViewById
			if(convertView==null){
				convertView=View.inflate(MainActivity.this, R.layout.listview, null);
			}
			TextView tv=(TextView)convertView.findViewById(R.id.tv);
			text=data.get(position);
			tv.setText(text);
			return convertView;
		}

这样加载视图就只会调用它第一屏的条目的数量。比如:第一屏显示8个条目,加载视图会调用8次,以后滑动就不会调用了。

到这里看起来是可以了,但是我们可以注意到findViewById也到调用了100次呀,也挺多的,能不能减少呢,答案是肯定的。

那这就是所谓的 高档式

定义一个ViewHolder,将convertView的tag设置为ViewHolder,不为空时重新使用

ViewHolder只是将需要缓存的那些view封装好,convertView的setTag才是将这些缓存起来供下次调用

当你的listview里布局多样化的时候 viewholder的作用就有比较明显的体现了。 当然了,单一模式的布局一样有性能优化的作用 只是不直观。

viewholder就是个静态类 与缓存无关的

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			// TODO Auto-generated method stub
			/*LayoutInflater layoutInflater=LayoutInflater.from(MainActivity.this);
			View view=layoutInflater.inflate(R.layout.listview, null);*/
			//高档式
			ViewHolder holder;
			String data ;
			if(convertView!=null&&convertView instanceof ViewGroup) {
				holder=(ViewHolder) convertView.getTag();
			}
			else{
				convertView=View.inflate(MainActivity.this, R.layout.listview, null);
				holder=new ViewHolder();
				holder.tv=(TextView) convertView.findViewById(R.id.tv);
				convertView.setTag(holder);//setTag用于携带数据
			}
			return convertView;
		}

 
	//static--只执行一次,而且先执行
	static class ViewHolder{
		TextView tv;
	}

为什么要这样写呢

if (convertView != null && convertView instanceof ViewGroup) {}

因为头的布局和item的布局不一样,不能够全部复用,所以要判断下。

这样就又减少了findViewById的次数了,又再一次优化了。

优化完成了,接下来实现分类显示,首先分析:

数据0-99,分成奇数和偶数,所以各有50个,头的位置分别加在 position = 0 的时候和 position = 51 的时候。

所以:

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			// TODO Auto-generated method stub
			/*LayoutInflater layoutInflater=LayoutInflater.from(MainActivity.this);
			View view=layoutInflater.inflate(R.layout.listview, null);*/
			//高档式
			ViewHolder holder;
			String data ;
			
			if(position==0){
				TextView tv=new TextView(getApplicationContext());
				tv.setText("奇数:"+jiData.size());
				return tv;
			}else if(position<=jiData.size()){
				data=jiData.get(position-1);
			}else if(position==jiData.size()+1){
				TextView tv2=new TextView(getApplicationContext());
				tv2.setText("偶数:"+ouData.size());
				return tv2;
			}else{
				data=ouData.get(position-1-jiData.size()-1);
			}
			return convertView;
		}
		
	}
到这里就已经实现了上面的效果。

MainActivity:

public class MainActivity extends Activity {

	private ListView listview;
	private List<String>data;
	private List<String>jiData;//奇数
	private List<String>ouData;//偶数
	private String text;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		listview=(ListView) findViewById(R.id.listview);
		jiData=new ArrayList<String>();
		ouData=new ArrayList<String>();
		for(int i=1;i<=100;i++){
			if(i%2==0)
				ouData.add(i+"");
			else
			    jiData.add(i+"");
		}
		listview.setAdapter(new MyAdapter());
	}

	class MyAdapter extends BaseAdapter{

		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return 1+jiData.size()+1+ouData.size();
		}

		@Override
		public Object getItem(int position) {
			// TODO Auto-generated method stub
			//俩者效果一样
			return null;
			//return data.get(position);
		}

		@Override
		public long getItemId(int position) {
			// TODO Auto-generated method stub
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			// TODO Auto-generated method stub
			/*LayoutInflater layoutInflater=LayoutInflater.from(MainActivity.this);
			View view=layoutInflater.inflate(R.layout.listview, null);*/
			//高档式
			ViewHolder holder;
			String data ;
			
			if(position==0){
				TextView tv=new TextView(getApplicationContext());
				tv.setText("奇数:"+jiData.size());
				return tv;
			}else if(position<=jiData.size()){
				data=jiData.get(position-1);
			}else if(position==jiData.size()+1){
				TextView tv2=new TextView(getApplicationContext());
				tv2.setText("偶数:"+ouData.size());
				return tv2;
			}else{
				data=ouData.get(position-1-jiData.size()-1);
			}
			
			/*if(position<jiData.size())
				data=jiData.get(position);
			else
				data=ouData.get(position-jiData.size());*/
			
			if(convertView!=null&&convertView instanceof ViewGroup) {
				holder=(ViewHolder) convertView.getTag();
			}
			else{
				convertView=View.inflate(MainActivity.this, R.layout.listview, null);
				holder=new ViewHolder();
				holder.tv=(TextView) convertView.findViewById(R.id.tv);
				convertView.setTag(holder);//setTag用于携带数据
			}
			//text=data.get(position);
			//分偶数和奇数
			holder.tv.setText(data);
			return convertView;
		}
		
	}
	//static--只执行一次,而且先执行
	static class ViewHolder{
		TextView tv;
	}
}
源码: 下载



















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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值