Android Adapter全解析

在Adapter在开发中使用到的地方很多,经常是与ListView搭配使用,下面是android中adapter的继承结构,A:abstractClass、I:interface、C:class.
这里写图片描述
(这边的图,我在有道云笔记上面画的,但是CSDN貌似不识别这个语法,就截图出来了)

下面详细介绍每一种adapter的用法:

首先是具体实现类的使用

这类adapter用法简单,有现成的构造方法,我们只需要传入相应的参数,就可以很轻松的使用了。
1. ArrayAdapter

ArrayList<String> array = new ArrayList<String>();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.base_adapter, R.id.textView, array);

下面是base_adapter.xml的内容:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView 
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>

2.SimpleAdapter

List<Map<String,Object>> data = new ArrayList<Map<String,Object>>();
        Map<String,Object> data1 = new HashMap<String,Object>();
        data1.put("text", "first");
        data1.put("icon", R.drawable.ic_launcher);
        Map<String,Object> data2 = new HashMap<String,Object>();
        data2.put("text", "second");
        data2.put("icon", R.drawable.ic_launcher);
        data.add(data1);
        data.add(data2);
        listView = (ListView)this.findViewById(R.id.myList);
        SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.simple_adapter, 
                new String[]{"text","icon"}, new int[]{R.id.textView,R.id.imageView});
        listView.setAdapter(adapter);

下面是 simple_adapter 的布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView 
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ImageView 
        android:id="@+id/imageView"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        />
</LinearLayout>

下面是效果图:
simpleAdapter

3.SimpleCursorAdapter
看名字就知道了,数据源provider

Cursor cursor = getContentResolver().query(Phone.CONTENT_URI,
                new String[]{Phone._ID,Phone.NUMBER,Phone.DISPLAY_NAME}, 
                null, null, null);
        SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this, R.layout.simple_adapter, 
                cursor, new String[]{Phone.DISPLAY_NAME,Phone.NUMBER},
                new int[]{R.id.name,R.id.number},0x02);
        listView.setAdapter(cursorAdapter);

simple_adapter.xml的布局就不写了,就是两个TextVIew 。这边需要注意一点的就是,当cursor的内容设给adapter时,一定要有”_id”这一列。 这段代码读取了手机联系人的姓名和号码,效果如下:
SimpleCursorAdapter

以上的adapter是android帮我们实现好的,使用非常简单。但是listView中内容格式是完全一致的,如果想要实现差异化,那么就需要实现自己的adapter了。

自定义adapter

其实所谓的自定义adapter,就是去继承BaseAdapter和CursorAdapter啦

1.BaseAdapter
当我们继承BaseAdapter时,IDE会贴心的告诉我们需要复写下面的方法:getCount()、getItem(int position)、getItemId(int position)、getView(int position, View convertView, ViewGroup parent),我们来看一下SimpleAdapte中这几个方法的实现来了解一下这些方法的作用:

    private List<? extends Map<String, ?>> mData;
    public SimpleAdapter(Context context, List<? extends Map<String, ?>> data,
            @LayoutRes int resource, String[] from, @IdRes int[] to) {
        mData = data;
        mResource = mDropDownResource = resource;
        ...
    }
    /**
     * @see android.widget.Adapter#getCount()
     */
    public int getCount() {
        return mData.size();
    }

    /**
     * @see android.widget.Adapter#getItem(int)
     */
    public Object getItem(int position) {
        return mData.get(position);
    }

    /**
     * @see android.widget.Adapter#getItemId(int)
     */
    public long getItemId(int position) {
        return position;
    }

    /**
     * @see android.widget.Adapter#getView(int, View, ViewGroup)
     */
    public View getView(int position, View convertView, ViewGroup parent) {
        return createViewFromResource(mInflater, position, convertView, parent, mResource);
    }
    private View createViewFromResource(LayoutInflater inflater, int position, View convertView,
            ViewGroup parent, int resource) {
        View v;
        if (convertView == null) {
            v = inflater.inflate(resource, parent, false);
        } else {
            v = convertView;
        }

        bindView(position, v);

        return v;
    }

首先看getCount(),他返回的是adapter中内容的数量;
再看getView()方法,他调用了inflater.inflate(resource, parent, false);加载了我们在构造SimpleAdapter时传入的布局ID;
再来看getItem(),返回的就是adapter的内容啦;getItemId()就是listView中位置对应在adapter数据的位置,这边返回的就是listView的位置,因为基本上adapter总的内容在填充一个listView时,位置肯定就是一一对应的啦。

我们现在来实现一个这样的adapter,它包含一个textView和一个checkBox,但是要求这个CheckBox显示出来是随机的,先看布局,很简单:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView 
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
    <CheckBox 
        android:id="@+id/checkBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>

再来看adapter的实现:

public class MyBaseAdapter extends BaseAdapter {
    private final LayoutInflater mLayoutInflater;
    private List<String> list;
    private Context mContext;
    public MyBaseAdapter(Context context,ArrayList<String> arrayList){
        mLayoutInflater = LayoutInflater.from(context);
        list = arrayList;
        mContext = context;
    }
    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        if(list!=null){
            return list.size();
        }else{
            return 0;
        }
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        LinearLayout view = null;
        if (convertView != null) {
            view = (LinearLayout)convertView;
        } else {
            view = (LinearLayout)mLayoutInflater.inflate(R.layout.simple_adapter, parent,false);
        }
        TextView tv = (TextView)view.findViewById(R.id.textView);
        tv.setText(list.get(position));
        CheckBox check = (CheckBox)view.findViewById(R.id.checkBox);
        Random random = new Random();
        boolean show = random.nextBoolean();
        if(show){
            check.setVisibility(View.VISIBLE);
        }else{
            check.setVisibility(View.GONE);
        }
        return view;
    }
}

最后在activity中使用一下:

ArrayList<String> array = new ArrayList<String>();
        array.add("aaaa");
        array.add("bbbb");
        array.add("cccc");
        array.add("dddd");
        array.add("eeee");
        array.add("ffff");
        array.add("gggg");
        array.add("hhhh");
        array.add("iiii");
        listView.setAdapter(new MyBaseAdapter(this,array));

最终看下效果图
myBaseAdapter

2.CursorAdapter
继承这个类只需要实现两个方法,就是newView()和bindView,当然还得实现的就是构造方法,好把cursor往上传,让getCount()方法能够得到正确的返回值。
其实newView()和bindView(),在两个方法都会在getView()中调用,getView()方法在每绘制一个数据时,都会被执行,不管之前有木有绘制过,也就是说如果我们来回滑动listView,那么getView()方法一直会被调用。但是我们来看一下CursorAdapter中的getView()方法

View v;
        if (convertView == null) {
            v = newView(mContext, mCursor, parent);
        } else {
            v = convertView;
        }
        bindView(v, mContext, mCursor);

就很容易会发现,只要这个View创建好了,newView()就不会再调用啦,反应到我们的adapter中就是,adapter有多少个数据,就会调用多少个newView(),但是每绘制一个view,都会调用bindView。

下面是一个小的例子:
首先布局就不写了,只有两个TextView

然后要继承CursorAdapter

public class MyCursorAdapter extends CursorAdapter {

    private LayoutInflater inflater;
    private Cursor cursor;
    public MyCursorAdapter(Context context, Cursor c, boolean autoRequery) {
        super(context, c, autoRequery);
        inflater = LayoutInflater.from(context);
        cursor = c;
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return inflater.inflate(R.layout.simple_adapter, parent, false);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        TextView name = (TextView)view.findViewById(R.id.name);
        TextView number = (TextView)view.findViewById(R.id.number);
        name.setText(cursor.getString(1));
        number.setText(cursor.getString(2));

    }

}

在activity中使用一下:

Cursor cursor = this.getContentResolver().query(Phone.CONTENT_URI,
                new String[]{Phone._ID,Phone.DISPLAY_NAME,Phone.NUMBER},
                null,null,null);
        MyCursorAdapter adapter = new MyCursorAdapter(this,cursor,false);
        listView.setAdapter(adapter);

最后一张效果图:
MyCursorAdapter

可以看到跟SimpleACursorAdapter一样,但是实现完全不同啦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值