当前位置: 代码迷 >> Android >> android:ListView缓存机制及BaseAdapter的三重意境(逗比式,普通式,文艺式)
  详细解决方案

android:ListView缓存机制及BaseAdapter的三重意境(逗比式,普通式,文艺式)

热度:113   发布时间:2016-04-24 11:40:21.0
android:ListView缓存机制及BaseAdapter的三重境界(逗比式,普通式,文艺式)

大家都知道listview的格式是一定的 而数据源确是多重多样的 这时候 就需要一种适配器来把数据源转换成listview要显示的格式

baseAdapter就诞生了。

listview和gridView的显示和缓存机制 如下图

大家都知道屏幕的大小是有限的 可是listview中的数据却可能很多 所以手机不能一下子展示所有的数据 它只会加载屏幕上显示的数据 。

如上图,当我们把屏幕往下滑动时 item1回收到recycler 而item8要显示在屏幕上 item8从recycler取出这样一个布局文件 并重新设置好item8要显示的数据 并设置要要显示的位置。总之一句话 需要才显示 显示完就被回收到缓存。

至于题目为何说BaseAdapter的三重境界(逗比式,普通式,文艺式) 区别在哪里那?就在如何运用listview的显示和缓存机制

在listview的适配器上 有这样一个方法

	@Override	public View getView(int position, View convertView, ViewGroup parent) {		// TODO Auto-generated method stub		return null;	}

其中逗比式 普通式 文艺式的区别就在于如何使用这个方法

下面我们通过一个实例 来比较adapter的三重境界孰强孰弱

要实现的效果如下


activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <ListView         android:id="@+id/lv_listView"        android:layout_width="match_parent"        android:layout_height="match_parent"        ></ListView></LinearLayout>

item.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <ImageView        android:id="@+id/iv_image"        android:layout_width="50dp"        android:layout_height="50dp"        android:layout_alignParentLeft="true"        android:src="@drawable/ic_launcher" />    <TextView        android:id="@+id/tv_nickName"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_toRightOf="@id/iv_image"        android:gravity="center_horizontal"        android:textSize="20sp"        android:text="昵称" />    <TextView        android:id="@+id/tv_content"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_toRightOf="@id/iv_image"        android:layout_below="@id/tv_nickName"        android:textSize="15sp"        android:text="内容" /></RelativeLayout>

为了方便 ,我创建了一个myObject对象 用来封装item.xml要显示的数据

MyObject.class

package com.example.baseadapter;import android.widget.ImageView;import android.widget.TextView;public class MyObject {	private int imageViewId;	private String nickName;	private String content;	public MyObject(int imageViewId, String nickName, String content) {		this.imageViewId = imageViewId;		this.nickName = nickName;		this.content = content;	}	public String getNickName() {		return nickName;	}	public String getContent() {		return content;	}	public int getImageViewId() {		return imageViewId;	}}

MainActivity.class
package com.example.baseadapter;import java.util.ArrayList;import java.util.List;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.widget.ListView;public class MainActivity extends Activity {	private List<MyObject> list=new ArrayList<MyObject>();	private ListView listView;	private MyAdapter myAdapter;	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.activity_main);		listView=(ListView) findViewById(R.id.lv_listView);		for(int i=0;i<50;i++){			list.add(new MyObject(R.drawable.ic_launcher, "昵称"+i,	"内容"+i));		}		myAdapter=new MyAdapter(list, this);		listView.setAdapter(myAdapter);	}}

自定义的adapter

MyAdapter.class

package com.example.baseadapter;import java.util.List;import android.content.Context;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;public class MyAdapter extends BaseAdapter {	private long sum = 0;	private List<MyObject> list;	private Context context;	public MyAdapter(List<MyObject> list, Context context) {		this.list = list;		this.context = context;	}	@Override	public int getCount() {		// TODO Auto-generated method stub		return list.size();	}	@Override	public Object getItem(int position) {		// TODO Auto-generated method stub		return list.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		// 逗比式		 long star = System.nanoTime();		 View view=View.inflate(context, R.layout.item, null);		 ImageView imageView =(ImageView) view.findViewById(R.id.iv_image);		 TextView nickName=(TextView) view.findViewById(R.id.tv_nickName);		 TextView content=(TextView) view.findViewById(R.id.tv_content);		 MyObject myObject=list.get(position);		 imageView.setBackgroundResource(myObject.getImageViewId());		 nickName.setText(myObject.getNickName());		 content.setText(myObject.getContent());		 long end = System.nanoTime();		 sum += end - star;		 Log.d("main", "逗比式" + sum);		 return view;		// 普通式//		long star = System.nanoTime();//获取系统纳秒时间//		if (convertView == null) {//			convertView = View.inflate(context, R.layout.item, null);//		}//		ImageView imageView = (ImageView) convertView//				.findViewById(R.id.iv_image);//		TextView nickName = (TextView) convertView//				.findViewById(R.id.tv_nickName);//		TextView content = (TextView) convertView.findViewById(R.id.tv_content);//		MyObject myObject = list.get(position);//		imageView.setBackgroundResource(myObject.getImageViewId());//		nickName.setText(myObject.getNickName());//		content.setText(myObject.getContent());//		long end = System.nanoTime();//		sum += end - star;//		Log.d("main", "普通式" + sum);//		return convertView;		// 文艺式		// long star = System.nanoTime();		// ViewHolder viewHolder;		// if (convertView == null) {		// viewHolder=new ViewHolder();		// convertView = View.inflate(context, R.layout.item, null);		// viewHolder.imageView = (ImageView) convertView		// .findViewById(R.id.iv_image);		// viewHolder.nickName = (TextView) convertView		// .findViewById(R.id.tv_nickName);		// viewHolder.content = (TextView) convertView		// .findViewById(R.id.tv_content);		// //通过setTag方式 使viewHolder和convertView绑定在一起		// convertView.setTag(viewHolder);		// }		// viewHolder=(ViewHolder) convertView.getTag();		// MyObject myObject = list.get(position);		// viewHolder.imageView.setBackgroundResource(myObject.getImageViewId());		// viewHolder.nickName.setText(myObject.getNickName());		// viewHolder.content.setText(myObject.getContent());		// long end = System.nanoTime();		// sum += end - star;		// Log.d("main", "文艺式"+sum);		// return convertView;	}	// 避免重复的findViewById	class ViewHolder {		public ImageView imageView;		private TextView nickName;		private TextView content;	}}

BaseAdapter的三重境界(逗比式,普通式,文艺式)的代码已经在上面 

下面我们分析一下第一种为什么叫逗比式

前面已经说了,liseview具有缓存机制 可以将使用过的item放入缓冲池中,而在这里 每次调用getview方法的时候 我们都是创建新的view对象 并没有利用listview的缓存机制

没有任何处理 ,效率及其低下,所以我们称它为逗比式

而第二种 普通式是利用了getview方法中传入的contentview对象 并且加一个if判断

		if (convertView == null) {			convertView = View.inflate(context, R.layout.item, null);		}
虽然只是一个if判断  但是 通过这个判断 可以避免创建大量的contentview对象 节省了大量的时间 利用了ListView的缓存特性 如果没有缓存才创建新的view 对getview方法进行了非常好的优化  但这仅仅只算入门,因为findViewById依然会浪费大量的时间 所以我们称这种方法为普通式

那么第三种境界 文艺式 就是对findViewById的优化了 把findViewById 也放入if判断语句中 就ok了

我们需要创建一个内部类 里面有三个成员变量 都是我们item.xml文件中的三个控件

	class ViewHolder {		public ImageView imageView;		private TextView nickName;		private TextView content;	}
通过viewHolder.setTag()方法 把viewHolder和contentView关联在一起 然后通过getTag方法得到viewHolder

这种方法不仅利用了listview的缓存,更通过viewHolder来实现显示视图的缓存,避免多次使用findViewById方法

作为一个有情怀的程序员 这才是最文艺的写法~

大家可能看到了我代码中输出的log日志 下面我附上结果 大家比较一下 这里listview中只有50条数据 全部是滑倒底部



至此BaseAdapter的三重境界(逗比式,普通式,文艺式)孰强孰弱 一目了然~(如果有出入 请你把listview中的数据设置多一些)


参考: 慕课网

  相关解决方案