Android Adapter 详解

 我们在开发Android应用程序的时候,一般会用到Adapter这个接口的子类,它继承结构如下:

android.widget.Adapter,所以可以想象它的大体用途。它间接的子类有:ArrayAdapter<T>, BaseAdapterCursorAdapterHeaderViewListAdapterListAdapterResourceCursorAdapterSimpleAdapterSimpleCursorAdapterSpinnerAdapter,WrapperListAdapter。
它是AdapterView视图与数据之间的桥梁,Adapter提供对数据的访问,也负责为每一项数据产生一个对应的View。其作用如下图所示:


                   < Data、Adapter、View三者的关系>


                                      < 适配器的继承结构>

Adapter有两个常量:

int IGNORE_ITEM_VIEW_TYPE :一个项目视图类型导致AdapterView忽视项目视图。
int NO_SELECTION


Adapter公共方法:

1.abstract int getCount():有多少项目在数据集所代表的适配器。

2.abstract Object getItem(int position):获得相关的数据项中的指定位置的数据集。

3.abstract long getItemId(int position):获得和表里特定位置的相关联的行id。

4.abstract int getItemViewType(int position)

5.abstract View getView(int position, View convertView, ViewGroup parent)

6.abstract int getViewTypeCount()

7.abstract boolean hasStableIds()

8.abstract boolean isEmpty()

9.abstract void registerDataSetObserver(DataSetObserver observer)

10.abstract void unregisterDataSetObserver(DataSetObserver observer) 

在我们使用过程中可以根据自己的需求实现接口或者继承类进行一定的 扩展。比较常用的有 BaseAdapter,SimpleAdapter,ArrayAdapter,SimpleCursorAdapter等。

  • BaseAdapter是一个抽象类,继承它需要实现较多的方法,所以也就具有较高的灵活性;
  • ArrayAdapter支持泛型操作,最为简单,只能展示一行字。
  • SimpleAdapter有最好的扩充性,可以自定义出各种效果。
  • SimpleCursorAdapter可以适用于简单的纯文字型ListView,它需要Cursor的字段和UI的id对应起来。如需要实现 更复杂的UI也可以重写其他方法。可以认为是SimpleAdapter对数据库的简单结合,可以方便地把数据库的内容以列表的形式展示出来。

1)ArrayAdapter

列表的显示需要三个元素:

a.ListVeiw: 用来展示列表的View。

b.适配器: 用来把数据映射到ListView上的桥梁。

c.数据:具体的将被映射的字符串,图片,或者基本组件。

public class ArrayAdapterActivity extends Activity { 

    //private List<String> data = new ArrayList<String>();

    @Override

    public void onCreate(Bundle savedInstanceState){

        super.onCreate(savedInstanceState);  

        ListView listView=(ListView)findViewById(R.id.listview);

        listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,getData()));

        setContentView(listView);

    }

    private List<String> getData(){

        List<String> data = new ArrayList<String>();

        data.add("测试数据1");

        data.add("测试数据2");

        data.add("测试数据3");

        data.add("测试数据4");

        return data;

    }

}


2)SimpleAdapter 
simpleAdapter的 扩展性最好,可以定义各种各样的布局出来,可以放上ImageView(图片),还可以放上Button(按钮),CheckBox(复选框)等等。下面 的代码都直接继承了ListActivity,ListActivity和普通的Activity没有太大的差别,不同就是对显示ListView做了许 多优化,方面显示而已。

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

<ImageView

android:id="@+id/img"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="5dp"

/>

<TextView

android:id="@+id/title"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:textColor="#ffffff"

android:textSize="20sp"

/>

</LinearLayout>

------------------------------

public class AtestActivity extends ListActivity {

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        //构造一个SimpleAdapter适配器

        SimpleAdapter adapter = new SimpleAdapter(this, getData(), R.layout.main, new String[] { "title",  "img" }, new int[] { R.id.title, R.id.img });

        setListAdapter(adapter);

    }

    //构造data部分

    private List<Map<String, Object>> getData() {

        //map.put(参数名字,参数值)

        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

        Map<String, Object> map = new HashMap<String, Object>();

        map.put("title", "摩托罗拉");

        map.put("img", R.drawable.icon);

        list.add(map);

        map = new HashMap<String, Object>();

        map.put("title", "诺基亚");

        map.put("img", R.drawable.icon);

        list.add(map);

        map = new HashMap<String, Object>();

        map.put("title", "三星");

        map.put("img", R.drawable.icon);

        list.add(map);

        return list;

        } 

}

-------------------------------------------------

SimpleAdapter(Context context, List<? extends Map<String, ?>>  data, int resource, String[]  from, int[] to
      参数: 
      1,context:上下文。 
      2,data:基于Map的list。Data里边的每一项都和 ListView里边的每一项对应。Data里边的每一项都是一个Map类型,这个Map类里边包含了ListView每一行需要的数据。 
      3,resource :就是一个布局layout,可引用系统提供的,也可以自定义。 
      4,from:这是个名字数组,每个名字是为了在 ArrayList数组的每一个item索引Map<String,Object>的Object用的。即 map 中得key值 
      5,to:里面是一个TextView数组。这些 TextView是以id的形式来表示的。例如:Android.R.id.text1,这个text1在layout当中是可以索引的。

--------------------------------------------------------------

<?xml version="1.0" encoding="UTF-8"?>

   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

        android:orientation="horizontal" android:layout_width="fill_parent"

        android:layout_height="fill_parent">

        <ImageView android:id="@+id/img"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:scaleType="fitStart"

            android:layout_margin="5dp"/>

        <LinearLayout android:orientation="vertical"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content">

            <TextView android:id="@+id/title"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:textColor="#FFFFFFFF"

                android:textSize="22dp" />

            <TextView android:id="@+id/info"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:textColor="#FFFFFFFF"

                android:textSize="13dp" />

        </LinearLayout>

    </LinearLayout>

---------------

public class AMyListView3Activity extends ListActivity {

    // private List<String> data = new ArrayList<String>();

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        SimpleAdapter adapter = new SimpleAdapter(this,getData(),R.layout.vlist,

                new String[]{"title","info","img"},

                new int[]{R.id.title,R.id.info,R.id.img});

        setListAdapter(adapter);

    }

    private List<Map<String, Object>> getData() {

        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

        Map<String, Object> map = new HashMap<String, Object>();

        map.put("title", "G1");

        map.put("info", "google 1");

        map.put("img", R.drawable.i1);

        list.add(map);

        map = new HashMap<String, Object>();

        map.put("title", "G2");

        map.put("info", "google 2");

        map.put("img", R.drawable.i2);

        list.add(map);

        map = new HashMap<String, Object>();

        map.put("title", "G3");

        map.put("info", "google 3");

        map.put("img", R.drawable.i3);

        list.add(map);

        return list;

    }

}

使用simpleAdapter的数据用一般都是HashMap构成的List,list的每一节对应ListView的每一行。HashMap的每个键值数据映射到布局文件中对应id的组件上。因为系统没有对应的布局文件可用,我们可以自己定义一个布局vlist.xml。下面做适配,new一个SimpleAdapter参数一次是:this,布局文件(vlist.xml),HashMap的 title 和 info,img。布局文件的组件id,title,info,img。布局文件的各组件分别映射到HashMap的各元素上,完成适配。


3)SimpleCursorAdapter

简单的说就是方便把从游标得到的数据进行列表显示,并可以把指定的列映射到对应的TextView中。

public class SimpleCursorAdapterActivity extends ListActivity {

     @Override

     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         //获得一个指向系统通讯录数据库的Cursor对象获得数据来源

         Cursor cur = getContentResolver().query(People.CONTENT_URI, null, null, null, null);

     //我们将获得的Cursor对象交由Activity管理,这样Cursor的生命周期和Activity便能够自动同步,省去自己手动管理Cursor

         startManagingCursor(cur);

         //实例化列表适配器

         ListAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cur, new String[] {People.NAME}, new int[] {android.R.id.text1});

         setListAdapter(adapter);

     }

}

一定要以数据库作为数据源的时候,才能使用SimpleCursorAdapter,这里特别需要注意的一点是:不要忘了在AndroidManifest.xml文件中加入权限

<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>


4)BaseAdapter
  有时候,列表不光会用来做显示用,我们同样可以在在上面添加按钮。添加按钮首先要写一个有按钮的xml文件,然后自然会想到用上面的方法定义一个适配器,然后将数据映射到布局文件上。但是事实并非这样,因为按钮是无法映射的,即使你成功的用布局文件显示出了按钮也无法添加按钮的响应,这时就要研 究一下ListView是如何现实的了,而且必须要重写一个类继承BaseAdapter。下面的示例将显示一个按钮和一个图片,两行字如果单击按钮将删除此按钮的所在行。并告诉你ListView究竟是如何工作的。

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
     
     
        <ImageView android:id="@+id/img"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5px"/>
     
        <LinearLayout android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
     
            <TextView android:id="@+id/title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#FFFFFFFF"
                android:textSize="22px" />
            <TextView android:id="@+id/info"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#FFFFFFFF"
                android:textSize="13px" />
     
        </LinearLayout>
     
     
        <Button android:id="@+id/view_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/s_view_btn"
            android:layout_gravity="bottom|right" />
    </LinearLayout>
-------------------------
    public class MyListView4 extends ListActivity {
     
     
        private List<Map<String, Object>> mData;
         
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mData = getData();
            MyAdapter adapter = new MyAdapter(this);
            setListAdapter(adapter);
        }
     
        private List<Map<String, Object>> getData() {
            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
     
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("title", "G1");
            map.put("info", "google 1");
            map.put("img", R.drawable.i1);
            list.add(map);
     
            map = new HashMap<String, Object>();
            map.put("title", "G2");
            map.put("info", "google 2");
            map.put("img", R.drawable.i2);
            list.add(map);
     
            map = new HashMap<String, Object>();
            map.put("title", "G3");
            map.put("info", "google 3");
            map.put("img", R.drawable.i3);
            list.add(map);
             
            return list;
        }
         
        // ListView 中某项被选中后的逻辑
        @Override
        protected void onListItemClick(ListView l, View v, int position, long id) {
             
            Log.v("MyListView4-click", (String)mData.get(position).get("title"));
        }
         
        /**
         * listview中点击按键弹出对话框
         */
        public void showInfo(){
            new AlertDialog.Builder(this)
            .setTitle("我的listview")
            .setMessage("介绍...")
            .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                }
            })
            .show();
             
        }
         
         
         
        public final class ViewHolder{
            public ImageView img;
            public TextView title;
            public TextView info;
            public Button viewBtn;
        }
         
         
        public class MyAdapter extends BaseAdapter{
     
            private LayoutInflater mInflater;
             
             
            public MyAdapter(Context context){
                this.mInflater = LayoutInflater.from(context);
            }
            @Override
            public int getCount() {
                // TODO Auto-generated method stub
                return mData.size();
            }
     
            @Override
            public Object getItem(int arg0) {
                // TODO Auto-generated method stub
                return null;
            }
     
            @Override
            public long getItemId(int arg0) {
                // TODO Auto-generated method stub
                return 0;
            }
     
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                 
                ViewHolder holder = null;
                if (convertView == null) {
                     
                    holder=new ViewHolder(); 
                     
                    convertView = mInflater.inflate(R.layout.vlist2, null);
                    holder.img = (ImageView)convertView.findViewById(R.id.img);
                    holder.title = (TextView)convertView.findViewById(R.id.title);
                    holder.info = (TextView)convertView.findViewById(R.id.info);
                    holder.viewBtn = (Button)convertView.findViewById(R.id.view_btn);
                    convertView.setTag(holder);
                     
                }else {
                     
                    holder = (ViewHolder)convertView.getTag();
                }
                 
                 
                holder.img.setBackgroundResource((Integer)mData.get(position).get("img"));
                holder.title.setText((String)mData.get(position).get("title"));
                holder.info.setText((String)mData.get(position).get("info"));
                 
                holder.viewBtn.setOnClickListener(new View.OnClickListener() {
                     
                    @Override
                    public void onClick(View v) {
                        showInfo();                
                    }
                });
                 
                 
                return convertView;
            }
             
        }
  
    }

listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度(这也是为什么在开始的第一张图特别的标出列表长度),然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的布局。我们用LayoutInflater的方法将定义好的vlist2.xml文件提取成View实例用来显示。然后将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点,只要布局文件中将Button设置为没有焦点就OK了。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Android Spinner 是一个下拉列表控件,用于在列表中显示多个选项,并允许用户从中选择一个。为了将数据显示在 Spinner 中,需要使用一个适配器(Adapter)来为 Spinner 提供数据源。 下面是一个简单的 Spinner 适配器示例: 1. 首先,创建一个数据源,它可以是任何类型的集合(如数组、列表等): ``` List<String> dataList = new ArrayList<>(); dataList.add("Option 1"); dataList.add("Option 2"); dataList.add("Option 3"); ``` 2. 创建一个 ArrayAdapter 对象来将数据源与 Spinner 控件关联起来: ``` ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, dataList); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); ``` 这里,ArrayAdapter 的构造函数需要传入三个参数:上下文、Spinner 控件使用的布局以及数据源。setDropDownViewResource() 方法用于为 Spinner 中的每个选项指定下拉列表的布局。 以上代码中,数据源为字符串列表,所以 ArrayAdapter 的泛型类型为 String。如果数据源是其他类型的集合,则需要相应地修改 ArrayAdapter 的泛型类型。 除了 ArrayAdapter,还有其他类型的适配器可用于 Spinner,例如 CursorAdapter 和 SimpleCursorAdapter,它们可用于显示从数据库中检索的数据。 ### 回答2: Android中的Spinner是一个下拉列表控件,它允许用户从预定义的选项中选择一个值。Spinner的显示和选择功能由Adapter控制。 Adapter在Spinner中扮演着重要的角色,它负责管理Spinner的数据来源并将数据显示在Spinner中。通过SpinnerAdapter接口,我们可以自定义Spinner的样式和布局。 在使用Spinner时,我们需要创建一个适配器来将数据绑定到Spinner上。适配器可以是ArrayAdapter、CursorAdapter、SimpleAdapter等。适配器通过getView()方法来指定Spinner每个选项的视图,并将数据显示在Spinner中。 适配器的工作原理是通过getView()方法将每个选项的数据和布局进行绑定,并返回一个视图给Spinner显示。同时,适配器还可以为每个选项设置点击事件监听器。 使用Spinner和Adapter时,需要注意几个重要的方法。首先是setAdapter()方法,它用于为Spinner设置适配器。其次是getSelectedItem(),它可以获取用户选择的选项值。还有getCount()方法,用于获取Spinner中选项的数量。 另外,为了实现自定义的样式和布局,我们可以继承BaseAdapter类来创建自定义的适配器。在自定义适配器中,我们可以重写父类的getView()方法来实现不同的选项显示效果。 总而言之,Spinner和AdapterAndroid开发中非常常见和重要的控件和接口,它们能够方便地实现下拉列表的显示和选择功能。通过自定义适配器,我们可以轻松地实现Spinner的不同样式和布局。 ### 回答3: Android Spinner Adapter 是一个可以用来为 Spinner 组件提供数据源的适配器。在 Android 中,Spinner 是一个下拉列表的组件,用户可以通过点击下拉箭头选择其中的一项。为了提供下拉列表中的选项数据,我们需要使用 Spinner Adapter。 Spinner Adapter 是一个通用的接口,我们可以通过实现该接口来创建自定义的 Adapter 来为 Spinner 提供数据。我们可以通过重写 Adapter 的方法来定义列表的样式、数据结构和展示方式。 Spinner Adapter 中最重要的方法是 getCount()、getItem() 和 getView()。getCount() 用于返回列表的长度,即下拉列表中有多少个选项。getItem() 用于返回特定位置的数据项,而 getView() 用于获得列表中每个选项的视图。 在使用 Spinner Adapter 的时候,我们可以根据不同的数据类型选择不同的 Adapter。例如,如果数据是一个简单的字符串列表,我们可以使用 ArrayAdapter;如果数据是一个复杂的对象列表,我们可以使用 BaseAdapter 或者 RecyclerView.Adapter。 如果我们希望自定义下拉列表的样式,我们还可以使用自定义的布局资源文件来为 Adapter 设置列表项的布局。我们可以通过重写 getView() 方法来实现这个功能,可以将自定义的布局资源文件与 Adapter 关联,同时可以使用 findViewById() 方法来获取布局中的视图元素,并将数据填充到这些视图中。 总而言之,Android Spinner Adapter 是一个用于为 Spinner 提供数据源的接口。通过实现 Adapter 接口并重写其中的方法,我们可以创建自定义的 Adapter 来为 Spinner 提供数据,并可以自定义下拉列表的样式和布局。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值