Android之listview优化+分类显示

来源:互联网 发布:淘宝网上代购可信吗 编辑:程序博客网 时间:2024/06/05 19:00

今天就来说说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;@Overrideprotected 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方法,前面几个这样写:

@Overridepublic int getCount() {// TODO Auto-generated method stubreturn 1+jiData.size()+1+ouData.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stub//俩者效果一样return null;//return data.get(position);}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}
现在来看看getView方法,在这个方法里我们要对listview优化和分类显示,所以代码量有点多~

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

@Overridepublic 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来减少加载布局的次数:

那就是所谓的普通式

@Overridepublic 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);*///普通式,虽然对视图进行了优化,不用每次都重新加载,但是每次都要findViewByIdif(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就是个静态类 与缓存无关的

@Overridepublic 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 的时候。

所以:

@Overridepublic 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;@Overrideprotected 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{@Overridepublic int getCount() {// TODO Auto-generated method stubreturn 1+jiData.size()+1+ouData.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stub//俩者效果一样return null;//return data.get(position);}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic 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);elsedata=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
原创粉丝点击