android:ListView缓存机制及BaseAdapter的三重境界(逗比式,普通式,文艺式)
2016-02-27 09:45
751 查看
大家都知道listview的格式是一定的 而数据源确是多重多样的 这时候 就需要一种适配器来把数据源转换成listview要显示的格式
baseAdapter就诞生了。
![](http://img.blog.csdn.net/20160226163243171)
listview和gridView的显示和缓存机制 如下图
![](http://img.blog.csdn.net/20160226163340213)
大家都知道屏幕的大小是有限的 可是listview中的数据却可能很多 所以手机不能一下子展示所有的数据 它只会加载屏幕上显示的数据 。
如上图,当我们把屏幕往下滑动时 item1回收到recycler 而item8要显示在屏幕上 item8从recycler取出这样一个布局文件 并重新设置好item8要显示的数据 并设置要要显示的位置。总之一句话 需要才显示 显示完就被回收到缓存。
至于题目为何说BaseAdapter的三重境界(逗比式,普通式,文艺式) 区别在哪里那?就在如何运用listview的显示和缓存机制
在listview的适配器上 有这样一个方法
其中逗比式 普通式 文艺式的区别就在于如何使用这个方法
下面我们通过一个实例 来比较adapter的三重境界孰强孰弱
要实现的效果如下
![](http://img.blog.csdn.net/20160226164543546)
activity_main.xml
item.xml
为了方便 ,我创建了一个myObject对象 用来封装item.xml要显示的数据
MyObject.class
MainActivity.class
自定义的adapter
MyAdapter.class
BaseAdapter的三重境界(逗比式,普通式,文艺式)的代码已经在上面
下面我们分析一下第一种为什么叫逗比式
前面已经说了,liseview具有缓存机制 可以将使用过的item放入缓冲池中,而在这里 每次调用getview方法的时候 我们都是创建新的view对象 并没有利用listview的缓存机制
没有任何处理 ,效率及其低下,所以我们称它为逗比式
而第二种 普通式是利用了getview方法中传入的contentview对象 并且加一个if判断
那么第三种境界 文艺式 就是对findViewById的优化了 把findViewById 也放入if判断语句中 就ok了
我们需要创建一个内部类 里面有三个成员变量 都是我们item.xml文件中的三个控件
这种方法不仅利用了listview的缓存,更通过viewHolder来实现显示视图的缓存,避免多次使用findViewById方法
作为一个有情怀的程序员 这才是最文艺的写法~
大家可能看到了我代码中输出的log日志 下面我附上结果 大家比较一下 这里listview中只有50条数据 全部是滑倒底部
![](http://img.blog.csdn.net/20160226170930680)
![](http://img.blog.csdn.net/20160226170937735)
![](http://img.blog.csdn.net/20160226170945274)
至此BaseAdapter的三重境界(逗比式,普通式,文艺式)孰强孰弱 一目了然~(如果有出入 请你把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 最火的快速开发框架XUtils
- Android如何定制化自己的开关机动画、开关机铃声
- android 让TextView自带滚动条
- Android本地数据安全尝试(中)——Conceal
- 浅谈Android App开发中Fragment的创建与生命周期
- android开发 不注意的异常
- Android如何查看应用签名信息
- Android.mk的一些FAQ
- 应用开机启动及相关文档翻译
- Android不规则瀑布流照片墙的实现+LruCache算法
- 个人进阶之路——自定义控件(5)
- android 8种对话框(Dialog)使用方法汇总
- Android Resources$NotFoundException异常
- android第一个项目-计算你的生存日子之年龄计算器
- [Android]开源中国源码分析之二---DrawerLayout
- Android的Activity跳转和传值
- android加载大量图片内存溢出的三种解决办法
- Android Fragment
- Android--Dialog对话框
- 【学习笔记】day1_快速入门 03_Android体系结构