【Android实战之旅 002】数据适配器BaseAdapter的使用与优化

来源:互联网 发布:mac dns被劫持 编辑:程序博客网 时间:2024/06/05 02:05

数据源(Data Source)的来源是各式各样的而ListView展示数据的格式却是有一定要求的。数据适配器就是建立了数据源和ListView的这样一个适配关系,将数据源的数据转换为ListView能够显示的格式。将数据的来源和数据的显示进行解耦,降低了程序的耦合性,使程序更加容易扩展。ListView的显示和缓存机制:滑出屏幕的显示区域的数据将这个Item回收到View缓存池中,新要显示的Item会从缓存区中取出设置到相应的位置,即需要的时候才显示,显示完后被回收到缓存区中。

一、创建布局文件

(1)在activity_main.xml中添加一个ListView

<?xml version="1.0" encoding="utf-8"?><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"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.davebobo.baseadapter.MainActivity">    <ListView        android:id="@+id/lv_main"        android:layout_width="match_parent"        android:layout_height="match_parent">    </ListView></RelativeLayout>
(2)新建一个Item布局(item.xml)作为ListView每个布局所要显示的内容

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="wrap_content">    <ImageView        android:id="@+id/iv_image"        android:layout_width="60dp"        android:layout_height="60dp"        android:src="@mipmap/ic_launcher"/>    <TextView        android:id="@+id/tv_title"        android:layout_width="match_parent"        android:layout_height="30dp"        android:layout_toRightOf="@+id/iv_image"        android:text="Title"        android:gravity="center"        android:textSize="25sp"/>    <TextView        android:id="@+id/tv_content"        android:layout_width="match_parent"        android:layout_height="30dp"        android:layout_toRightOf="@+id/iv_image"        android:layout_below="@+id/tv_title"        android:text="Content"        android:gravity="center_vertical"        android:textSize="20sp"/></RelativeLayout>

二、创建数据源

创建ItemBean类并封装三个属性,通过Bean对象为我们要显示的数据与我们显示数据的Item布局文件形成一一映射关系。

package com.davebobo.baseadapter;/** * Created by DaveBobo on 2016/9/26. */public class ItemBean {    public int ItemImageResid;    public String ItemTitle;    public  String ItemContent;    public ItemBean(int itemImageResid, String itemTitle, String itemContent) {        ItemImageResid = itemImageResid;        ItemTitle = itemTitle;        ItemContent = itemContent;    }}
在main方法中创建假数据

package com.davebobo.baseadapter;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        List<ItemBean> itemBeansList = new ArrayList<>();        for (int i=0;i<20;i++){        itemBeansList.add(new ItemBean(R.mipmap.ic_launcher,                "我是标题"+i,                "我是内容"+i));        }    }}

三、创建数据适配器

创建MyAdapter类继承BaseAdapter,通过LayoutInflater对象将一个xml文件(resource)转换为View

方式一:没有任何优化处理,每次都创建新的View,设置空控件,效率低

方式二:利用ListView的缓存特性,如果没有缓存才创建新的View,但是findViewById依然会浪费大量时间。

方式三:不仅利用ListView的缓存,更通过ViewHolder类来实现显示数据的视图的缓存,避免多次通过findViewById寻找控件。

package com.davebobo.baseadapter;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.List;/** * Created by DaveBobo on 2016/9/26. */public class MyAdapter extends BaseAdapter{    private List<ItemBean> mList;    private LayoutInflater mInflater;    public MyAdapter(Context context,List<ItemBean> list) {        mList = list;        mInflater = LayoutInflater.from(context);//context:要使用当前的Adapter的界面对象  mInflater:布局装载器对象    }    @Override    public int getCount() {        return mList.size();//返回ListView需要显示的数据数量    }    @Override    public Object getItem(int position) {        return mList.get(position);    }    @Override    public long getItemId(int position) {        return position;//返回指定索引对应的数据项    }    //返回每一项的显示内容    @Override        public View getView(int position, View convertView, ViewGroup parent) {        //方式一:没有利用到ListView的缓存机制//        View view = mInflater.inflate(R.layout.item,null);//通过LayoutInflater对象将一个xml文件转换为View//        ImageView imageView = (ImageView) view.findViewById(R.id.iv_image);//        TextView title = (TextView) view.findViewById(R.id.tv_title);//        TextView content = (TextView) view.findViewById(R.id.tv_content);//        ItemBean bean = mList.get(position);//获得第position个ItemBean对象//        imageView.setImageResource(bean.ItemImageResid);//        title.setText(bean.ItemTitle);//        content.setText(bean.ItemContent);//        return view;        //方式二:使用系统提供的convertView  充分利用了ListView的缓存机制避免了重复地去创建convertView对象        //因为通过LayoutInflater对象将xml转换为View时非常耗时耗资源//        if (convertView==null){//            convertView = mInflater.inflate(R.layout.item,null);//        }//        ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_image);//        TextView title = (TextView) convertView.findViewById(R.id.tv_title);//        TextView content = (TextView) convertView.findViewById(R.id.tv_content);//        ItemBean bean = mList.get(position);//获得第position个ItemBean对象//        imageView.setImageResource(bean.ItemImageResid);//        title.setText(bean.ItemTitle);//        content.setText(bean.ItemContent);//        return convertView;        //方式三:        ViewHolder viewHolder;        if (convertView == null){            viewHolder = new ViewHolder();            convertView = mInflater.inflate(R.layout.item,null);            viewHolder.imageView = (ImageView) convertView.findViewById(R.id.iv_image);            viewHolder.title = (TextView) convertView.findViewById(R.id.tv_title);            viewHolder.content = (TextView) convertView.findViewById(R.id.tv_content);            convertView.setTag(viewHolder);//建立ViewHolder与convertView之间的关系        }else {            viewHolder = (ViewHolder)convertView.getTag();//当convertView不为空时,直接通过getTag方法将保存的对象取出来,通过成员变量取出来        }        ItemBean bean = mList.get(position);//获得第position个ItemBean对象        viewHolder.imageView.setImageResource(bean.ItemImageResid);        viewHolder.title.setText(bean.ItemTitle);        viewHolder.content.setText(bean.ItemContent);        return convertView;    }    class  ViewHolder{        public ImageView imageView;        public TextView title;        public TextView content;    }}
回到MainActivity建立ListView与Adapter之间的联系。在onCreate中添加

 ListView listView  = (ListView) findViewById(R.id.lv_main);        listView.setAdapter(new MyAdapter(this,itemBeansList));
运行模拟器显示为

一些总结:

public int getCount():  适配器中数据集中数据的个数
public Object getItem(int position):  获取数据集中与指定索引对应的数据项
public long getItemId(int position):  获取指定行对应的ID
public View getView(int position, View convertView, ViewGroup parent):  获取每个Item的显示内容。

ViewHolder优化BaseAdapter思路:

创建Beam对象用于封装数据

在构造方法中初始化用于映射的数据List

创建ViewHolder类,创建布局映射关系

判断convertView,为空则创建,并设置tag,否则通过tag来取出ViewHolder

给ViewHolder中的控件设置数据

0 0