android:ListView缓存机制及BaseAdapter的三重境界(逗比式,普通式,文艺式)
Posted 甄情
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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中的数据设置多一些)
参考: 慕课网
以上是关于android:ListView缓存机制及BaseAdapter的三重境界(逗比式,普通式,文艺式)的主要内容,如果未能解决你的问题,请参考以下文章