什么是数据适配器
并且ListView内置缓存机制,显示在屏幕上的展示出来,不在屏幕上的缓存起来
编写代码步骤。
数据源:1:实体类的封装;
2:初始化数据;
适配器:编写自定义适配器;
主页面:适配器与视图之间的绑定;
- BaseAdapter的四个方法
主界面布局
<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"
>
<ListView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
item布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="50dp"
>
<ImageView
android:id="@+id/iv"
android:layout_alignParentLeft="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
/>
<TextView
android:id="@+id/tv_show"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:textSize="20sp"
android:layout_height="wrap_content"
android:text="文本內容"
/>
</RelativeLayout>
MainActivity 代码
public class MainActivity extends Activity {
private ListView lv;
private ArrayList<ItemBean> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//模拟ListView的数据
initData();
lv = (ListView) findViewById(R.id.lv);
//給ListView設置適配器
lv.setAdapter(new MyAdapter());
}
/**
* 模拟ListView的数据
*/
private void initData() {
list = new ArrayList<ItemBean>();
for(int i=1;i<=50;i++){
list.add(new ItemBean("我是标题"+i, R.drawable.ic_launcher));
}
}
class MyAdapter extends BaseAdapter{
//返回ListView条目的数量
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
//返回ListView显示的条目
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//..........
return null;
}
}
}
在上面代码中我们写了一个内部类集成BaseAdapter,重写了里面的四个方法.其中最重要的就是 getView() 方法
接下来我们先来看BasaAdapter的三种境界
逗比式
//返回ListView显示的条目
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//得到布局管理器
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
//..........
//逗比式
View view = inflater.inflate(R.layout.item, null);
TextView tv= (TextView)view.findViewById(R.id.tv_show);
ImageView iv = (ImageView)view.findViewById(R.id.iv);
tv.setText(list.get(position).tv);
iv.setImageResource(list.get(position).imageResourId);
return view;
}
效果如图;
可以看到listView每一项显示都是正确的,那我们为什么还要说它是逗比式呢.前面我们已经提到过,listView具有缓存机制,在getview() 方法所提供的参数中,有一个 convertView 就是listView为我们提供的一个缓存机制,但我们并没有用到,每次展示的view都是通过 View view = inflater.inflate(R.layout.item, null);
得到的.所以我们称这种方式为逗比式.
接下来我们做一些改进,
普通式
//返回ListView显示的条目
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//得到布局管理器
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
//..........
//普通式
if(convertView==null){
convertView = inflater.inflate(R.layout.item, null);
}
TextView tv= (TextView)convertView.findViewById(R.id.tv_show);
ImageView iv = (ImageView)convertView.findViewById(R.id.iv);
tv.setText(list.get(position).tv);
iv.setImageResource(list.get(position).imageResourId);
return convertView;
}
普通式其实就是运用listView给我们提供的缓存机制,也就是 convertView ,滑出屏幕的view都会被缓存在这个 convertView 中,当我们再次滑动让他们进入屏幕时,不必再通过 inflater.inflate(R.layout.item, null);
直接使用convertView即可,效果如图
其实到此我们还可以对listView做进一步的优化
文艺式
虽然我们已经对view进行了缓存,但是当listView快速滑动式 频繁的fingViewById() 方法也会浪费一些时间,我们可以 使用谷歌推荐的方法使用 ViewHolder 保存findViewById() 操作,避免频繁的 FindViewById(),节省时间,提高效率
//返回ListView显示的条目
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
//得到布局管理器
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
//..........
//文艺式
if(convertView==null){
convertView = inflater.inflate(R.layout.item, null);
holder = new ViewHolder();
holder.tv= (TextView)convertView.findViewById(R.id.tv_show);
holder.iv = (ImageView)convertView.findViewById(R.id.iv);
convertView.setTag(holder); //讲holder和缓存的view关联起来
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.tv.setText(list.get(position).tv);
holder.iv .setImageResource(list.get(position).imageResourId);
return convertView;
}
class ViewHolder{
public TextView tv;
public ImageView iv;
}
其实ViewHolder里面就是 item 的控件的引用,只有第一次展示view时才会findViewById(),之后都是从ViewHolder中取,当布局的嵌套层级比较深,比较复杂时,使用此方法会显著提高listView的滑动效率
效果图:
文艺式不仅利用了 ListView的缓存,更是通过ViewHolder类实现了显示视图数据的缓存,避免多次findViewById 寻找控件,提高了效率
作为一个有情怀的程序员,这才式最文艺的写法.