天天看点

【处女作】android中的ListView结合BaseAdapter实例 ,加入ViewHolder实现高性能ListView

基本上我的博客是根据我手头的项目来写,如有不对的地方,希望大家能给楼主指出来,在此先道声谢谢!

【处女作】android中的ListView结合BaseAdapter实例 ,加入ViewHolder实现高性能ListView

    android项目中需要制作一个类似于youtube的视频列表的界面,可采用ListView的方式实现,listView实现最好的方法就是配合Adapter(适配器)为其添数据,当然直接在java代码中为其添加数据也可以,但是不能实现动态数据的添加,比如说获取web服务器或者是其他程序中的数据。

关于Adapter:我们经常用"Men in the middle"中句话来描述它,也 就是“中间者”的意思。可以将它理解成数据和UI(View)之间的一个桥梁。

【处女作】android中的ListView结合BaseAdapter实例 ,加入ViewHolder实现高性能ListView

listview下的常用的adapter有:SimpleAdapter,ArrayAdapter,BaseAdapter等,其中我觉得最实用的就是BaseAdapter啦~

然后我们详细讲下这个。

BaseAdapter是个抽象类,继承它需要实现的方法有:

getCount(), getItem(int position), 

getItemId(int position),

getView(int position, View convertView, ViewGroup parent)

首先通过代码来简单介绍下:

class MyImgAdapter extends BaseAdapter {

		@Override
		public int getCount() {
			// 根据他的返回值得到 listView的长度
			return 0;
		}

		@Override
		public Object getItem(int position) {
			// 返回当前Item显示的数据,方便在Activity中的onItemClick方法中调用
			return null;
		}

		@Override
		public long getItemId(int position) {
			// 长按返回当前Item显示的数据,方便在Activity中的onItemClick方法中调用
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			// position就是位置从0开始,convertView是ListView中每一项要显示的view
			// 通常return 的view也就是convertView
			// parent就是父窗体了,也就是ListView了.
			return null;
		}
           

可能还有些小盆于看不明白,不要着急,看了下面的解释你就明白了

【处女作】android中的ListView结合BaseAdapter实例 ,加入ViewHolder实现高性能ListView

ListView绘制的过程如下:

第一步:系统在绘制ListView之前,将会先调用getCount方法来获取Item的个数。

第二步:开始绘制ListView列表,每绘制一个Item就会调用一次getView方法,在此方法内就可以引用事先定义好的xml来确定显示的效果并返回一个View对象作为一个Item显示出来。也正是在这个过程中完成了适配器的主要转换功能,把数据和资源以开发者想要的效果显示出来,一行行绘制,直到行数超过getCount()的返回值。

这两个方法是自定ListView显示效果中最为重要的,同时只要重写好了就两个方法,ListView就能完全按开发者的要求显示。而getItem和getItemId方法将会在调用ListView的响应方法的时候被调用到。所以要保证ListView的各个方法有效的话,这两个方法也得重写。比如:没有完成getItemId方法的功能实现的话,当调用ListView的getItemIdAtPosition()方法时将会得不到想要的结果,因为该方法就是调用了对应的适配器的getItemId方法。

接下来我们来写个简单的demo来实现下:

为了保证代码的高效性,以下的代码用到了一些优化策略,客官老爷们可以放心的直接用到项目中啦!!不过在写之前大家还需要了解下convertview和viewholder这两个东东。

convertview:官方解释是,The old view to reuse, if possible。原理上讲就是当ListView滑动的过程中 会有item被滑出屏幕 而不再被使用 这时候Android会回收这个条目的view 这个view也就是这里的convertView。

ViewHolder:

就是一个持有者的类,他里面一般没有方法,只有属性,作用就是一个临时的储存器,把你getView方法中每次返回的View存起来,可以下次再用。这样做的好处就是不必每次都到布局文件中去拿到你的View,提高了效率。      

第一步:新建一个android项目,我的项目名字是BaseAdapterDemo

第二步:修改activity_main.xml文件

<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"

    tools:context=".MainActivity" >

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

</RelativeLayout>
           

第三步:编写ListView的xml文件,这里我只添加了一个TextView,大家也可以加入其他东西。比如一个列表有可以点击的图片(ImageButton),相关信息的TextView,以及一些Button。

<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"

    tools:context=".MainActivity" >

   <TextView
        android:id="@+id/textview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>

</RelativeLayout>
           

第四步:编写MainActivity.java代码,在onCreate方法下面插入以下代码

class MyAdapter extends BaseAdapter {
		Context mContext;// 用于接收传递过来的Context对象
		LayoutInflater inflater;

		public MyAdapter(Context context) {
			mContext = context;
			inflater = LayoutInflater.from(mContext);
		}

		@Override
		public int getCount() {
			// 这里我就返回8了,也就是一共有8项数据项
			return 8;
		}

		@Override
		public Object getItem(int position) {
			// 返回当前Item显示的数据,方便在Activity中的onItemClick方法中调用
			return position;
		}

		@Override
		public long getItemId(int position) {
			// 长按返回当前Item显示的数据,方便在Activity中的onItemClick方法中调用
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder viewHolder = null;
			if (convertView != null) {
				// 当item1被移除屏幕的时候,我们会重新new一个View给新显示的item 而如果使用了这个convertView
				// 我们其实可以复用它,这样就省去了new View的大量开销
				convertView = inflater.inflate(R.layout.listitem1, parent, false);  
				viewHolder = new ViewHolder();  
				viewHolder.textView = (TextView)convertView.findViewById(R.id.textview);   
                convertView.setTag(viewHolder);  
                convertView.setTag(viewHolder);  
			} else {
				 // 没有供复用的view 按一般的做法新建view
				viewHolder = (ViewHolder) convertView.getTag();  
			}
			 //配置每个list的数据
			convertView.textView.setText(Integer.toString(position));  
			return convertView;
		}
	}

	// 定义的ViewHolder,非常简单,里面只有一个TextView
	class ViewHolder {
		TextView textView;
	}
           

第五步:运行项目就可以看到效果啦。

参考博文:

listview加载性能优化ViewHolder

利用convertView优化ListView性能

如果有问题欢迎邮件交流:我的邮箱[email protected]