AndroidAdapter详解

Android是完全遵循MVC模式设计的框架,ActivityController,layoutView。因为layout五花八门,很多数据都不能直接绑定上去,所以Android引入了Adapter这个机制作为复杂数据展示的转换载体,所以各种Adapter只不过是转换的方式和能力不一样而已。

Adapter是将数据绑定到UI界面上的桥接类。Adapter负责创建显示每个项目的子View和提供对下层数据的访问。

在多数情况下,你不需要创建自己的AdapterAndroid提供了一系列Adapter来将数据绑定到UIWidget上。

因为Android负责提供数据和选择用于显示每个项目的View,所以Adapter能快速地修改要绑定的控件的外观和功能。

Adapter是用来帮助填充数据的中间桥梁,比如通过它将数据填充到ListView,GridView,Gallery.

android提供了几种Adapter:ArrayAdapter,BaseAdapter,CursorAdapter,HeaderViewListAdapter,ListAdapter,ResourceCursorAdapter,SimpleAdapter,SimpleCursorAdapter,SpinnerAdapter,WrapperListAdapter.

根据数据来源形式的不同可以选择不同的Adapter,比如数据来源于一个Arraylist就使用BaseAdapter,SimpleAdapter,而数据来源于通过查询数据库获得Cursor那就使用

几种常用的Adapter:

Adapter应用总结

首先来看一下Adapter的体系结构:

一个Adapter的对象扮演一个桥梁的角色。这个桥梁连接着一个AdapterView和它所包含的数据。Adapter提供了一个通到数据项的途径。Adapter还负责为在数据集里的每个数据生项生成一个View。它有一个重要的方法:

publicabstractViewgetView(intposition,ViewconvertView,ViewGroupparent)这个方法被setListAdapteradapter)间接地调用。getView方法的作用是得到一个View,这个view显示数据项里指定位置的数据,你可以手动创建一个view或者从一个XMLlayoutinflate

当这个viewinflated,它的父view(如GridView,ListView等)将要使用默认的layout参数,除非你用inflate(int,android.view.ViewGroup,boolean)方法来指定一个根view并防止附着在根上。

下面分别讲一下它的几个常见的子类:

ListAdapter接口:继承于AdapterListAdapter是一个ListViewlist上的数据之间的桥梁。数据经常来自于一个Cursor,但这不是必须的。ListView能显示任何数据,只要它是被一个ListAdapter包装的。

BaseAdapter抽象类:是一个实现了既能在ListView(实现了ListAdapter接口)Spinner(实现了Spinner接口)里用的Adapter类的一般基类。

ArrayAdapter类:一个管理这样的ListViewListAdapter:这个ListView被一个数组所支持。这个数组可装任意对象。默认状态下,这个类预期能这样:提供的资源id与一个单独的TextView相关联。如果你想用一个更复杂的layout,就要用包含了域id的构造函数。

这个域id能够与一个在更大的layout资源里的TextView相关联。它将被在数组里的每个对象的toString()方法所填满。你可以添加通常对象的listsarrays。重写你对象的toString()方法来决定list里哪一个写有数据的text将被显示。

如果想用一些其它的不同于TextViewview来显示数组(比如ImageViews),或想有一些除了toString()返回值所填在views里的以外的数据,你就要重写getView(int,View,ViewGroup)方法来返回你想要的View类型。

SimpleCursorAdapter类:SimpleCursorAdapter绑定ViewContentProvider查询返回的游标上。指定一个XMLlayout定义,然后将数据集中的每一列的值绑定到layout中的一个View上。

SimpleAdapter类:一个使静态数据和在XML中定义的Views对应起来的简单adapter。你可以把list上的数据指定为一个Map范型的ArrayListArrayList里的每一个条目对应于list里的一行。Maps包含着每一行的数据。

你先要指定一个XML,这个XML定义了用于显示一行的view。你还要指定一个对应关系,这个对应关系是从Mapkeys对应到指定的views

绑定数据到views发生在两个阶段:如果一个simpleAdapter.ViewBinder是可用的,那么SetViewValue(android.view.View,Object,String)要被调用。如果返回true,那么绑定发生了。如果返回false,那么如下views将被按顺序地尝试:

~实现了CheckableView(如CheckBox),预期的绑定值是boolen

TextView,预期的绑定值是String,并且SetViewText方法被调用

ImageView,预期的绑定值是一个资源的idString。并且SetViewImage方法被调用

如果没有合适的绑定被发现,一个IllegalStateException被抛出。

不论是那种适配器模式,也不管是Listview也好还是gridview也好,对他们填充数据,都是分三步走。

第一:创建一个数据填充的对象,可以是ListView,GridView,Gallery

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

第二步:创建一个数据填充器,可以是BaseAdapterSimpleAdapter,也可以是与数据库相关联的CursorAdapter

例如:SimpleAdapter可以使用系统封装好的,你也可以自己去继承一个Simpleadapter,来重写其中的方法。继承simpleadapter的好处在于,你可以对listitem中每个单一的控件设置监听事件等等一系列操作。如果用的是系统封装好的就有点爱莫能助了。

直接使用系统封装的:

SimpleAdaptersimpleAdapter=newSimpleAdapter(this,data,R.layout.simple_item, newString[]{"name","info"},newint[]{R.id.simple_name,R.id.simple_info});

重写系统的simpleadpter

publicclassListSimpleAdpterextendsSimpleAdapter{

//要使用到的数据源

privateList<MAP><STRING,object="">>data=newArrayList<MAP><STRING,object="">>();

//填充数据的资源文件

privateintresource;

privateString[]from;

privateContextcontext;

publicListSimpleAdpter(Contextcontext,List<MAP><STRING,object="">>data,intresource,String[]from,int[]to){

super(context,data,resource,from,to);

this.context=context;

this.data=data;

this.resource=resource;

this.from=from;}

//item的总行数

@Override

publicintgetCount(){

returndata==null?0:data.size();

}

//item对象

@Override

publicObjectgetItem(intposition){

returnposition;

}

//itemid

@Override

publiclonggetItemId(intposition){

returnposition;

}

//绘制每一个item

@Override

publicViewgetView(intposition,ViewconvertView,ViewGroupparent){

Holderholder=null;

if(convertView==null){

convertView=LayoutInflater.from(context).inflate(resource,null);

holder=newHolder();

holder.imageView=(ImageView)convertView.findViewById(R.id.listitem_pic);

holder.title=(TextView)convertView.findViewById(R.id.listitem_title);

holder.content=(TextView)convertView.findViewById(R.id.listitem_content);

convertView.setTag(holder);

}else{

holder=(Holder)convertView.getTag();

}

holder.imageView.setImageResource(Integer.parseInt(data.get(position).get(from[0]).toString()));

holder.title.setText(data.get(position).get(from[1]).toString());

holder.content.setText(data.get(position).get(from[2]).toString());returnconvertView;

}

classHolder{

ImageViewimageView;

TextViewtitle;

TextViewcontent;

}

}

第三步:将数据填充到对象中去

listView.setAdapter(simpleAdapter);

这样就完成了数据填充器的数据填充。

下面是一个SimpleAdapter的例子:

/*--------------------TestUIList.java---------------------------*/

publicclassTestUIListextendsActivity{

publicvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

ListViewlist=(ListView)findViewById(R.id.MyListView);

ArrayList>lstImageItem=newArrayList>();

String[]str1={"rowone","rowtwo","rowthree","rowfour"};

String[]str2={"第一行","第二行","第三行","第四行"};

for(inti=0;i<str1.length;i++){

HashMapmap=newHashMap();

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

map.put("ItemTitle",str1[i]);

map.put("ItemText",str2[i]);

lstImageItem.add(map);

}

SimpleAdaptersaImageItems=newSimpleAdapter(this,

lstImageItem,

R.layout.simple_list_item_2,

newString[]{"ItemImage","ItemTitle","ItemText"},

newint[]{R.id.ItemImage,R.id.ItemTitle,R.id.ItemText});

list.setAdapter(saImageItems);

}

}

如果你的ListView的每一行想实现被点击后有响应事件。最省事的方法是继承一个ListActivityListActivity是一个这样的Activity:这个Activity能通过绑定到一个像arraycursor这样的数据源来显示一些itemslist,并且当用户选了一个item时,能够暴露事件句柄。

ListActivity拥有一个ListView对象。这个ListView对象能够被绑定到不同的数据源,特别是一个数组或者一个拥有查询结果的CursorListActivity有三种用法,分别是Binding,ScreenLayoutRowLayout。下面仅讨论一下ScreenLayout

ListActivity有一个默认的layout。这个layout是由一个在屏幕中央的、单独的、全屏的list构成。然而,如果你想的话,你可以通过在onCreate()里调用setContentView()方法来设置你自己的viewlayout的方式制定屏幕layout

要这样做,你自己的view必须包含一个id为“@android:id/android:list”(或者在代码中有list对象)。

当你制定这个view是空的时,你能够包含任何类型的view对象来显示。这个“空list”通知者必须有一个idandroid:empty”。

注意,最后一定要调用setListAdapter(adapter)方法来把通过Adapter绑定了数据的这个List显示出来。setListAdapter方法间接调用了AdaptergetView方法,其作用是返回你想要的view类型。

而且当点击listView里的item时,会根据getView重画这个ListView。例子可参见《AndroidSDK开发大全》中的“资源管理器“的例子。

想要实现事件监听,就要重写protectedvoidonListItemClick(ListViewl,Viewv,intposition,longid)方法。

想要把在XML中自定义了一行的view逐行显示在ListActivity中自定义的ListView中,并且在每行动态绑定数据的话,一般要自己写一个MyAdapter类,这个Adapter继承BaseAdapter并且其构造函数中至少有一个List参数来实现动态绑定数据。有两个重要的步骤:

1)重写getView方法,其中一重要步骤就是用items.get(position)方法来获得被传入的数据。其中items是一个List,它被赋了传入的List参数的值。position是这个数据在ListView中的行数。Get返回的是E类型.List中的模板类型。

2)写一个内部类privateclassViewHolder。这个内部类只有成员变量,它们就是你想在ListView中的一行里要显示的小View成分。

要想在Adapter中动态传入其它类的数据,就要在构造函数中再增加一个(或更多)List参数。

最后给出自己写的MyAdapter配合ListActivity实现监听事件的例子:

/*--------------------MyHome.java-----------------------*/

publicclassMyHomeextendsListActivity

{

privateListitems=null;

protectedvoidonCreate(Bundleicicle)

{

super.onCreate(icicle);

setContentView(R.layout.main);

items=newArrayList();

String[]titles=

{"默认主题","主题A","主题B","中秋佳节","粉红女郎","花样年华"};

for(inti=0;i<titles.length;i++)

{

Stringtitle=titles[i];

items.add(title);

}

setListAdapter(newMyAdapter(this,items));

}

@Override

protectedvoidonListItemClick(ListViewl,Viewv,intposition,

longid)

{

newAlertDialog.Builder(MyHome.this).setItems(

R.array.items_my_dialog,newDialogInterface.OnClickListener()

{

publicvoidonClick(DialogInterfacedialog,intwhichcountry)

{}

})

.show();

}

}

/*--------------------MyAdapter.java-----------------------*/

publicclassMyAdapterextendsBaseAdapter

{

privateLayoutInflatermInflater;

privateBitmapicom_theme;

privateBitmapicon_selected32;

privateListitems;

publicMyAdapter(Contextcontext,Listit)

{

mInflater=LayoutInflater.from(context);

items=it;

icom_theme=BitmapFactory.decodeResource(context.getResources(),R.drawable.theme);

icon_selected32=BitmapFactory.decodeResource(context.getResources(),R.drawable.selected32);

}

publicintgetCount()

{

returnitems.size();

}

publicObjectgetItem(intposition)

{

returnitems.get(position);

}

publiclonggetItemId(intposition)

{

returnposition;

}

publicViewgetView(intposition,ViewconvertView,ViewGroupparent)

{

ViewHolderholder;

convertView=mInflater.inflate(R.layout.file_row,null);

holder=newViewHolder();

holder.text=(TextView)convertView.findViewById(R.id.text);

holder.mTheme=(ImageView)convertView.findViewById(R.id.theme);

holder.mSelected32=(ImageView)convertView.findViewById(R.id.selected32);

holder.mTheme.setImageBitmap(icom_theme);

Stringtitle=items.get(position);

holder.text.setText(title);

holder.mSelected32.setImageBitmap(icon_selected32);

returnconvertView;

}

privateclassViewHolder

{

TextViewtext;

ImageViewmTheme;

ImageViewmSelected32;

}

}

dapterAndroid中占据一个重要的角色,它是数据和UIView)之间一个重要的纽带。在常见的View(ListView,GridView)等地方都需要用到Adapter。如图1直观的表达了DataAdapterView三者的关系。


更多相关文章

  1. Android(安卓)开发中使用 SQLite 数据库
  2. Android文件操作中的openFileOutPut和openFileInput
  3. Android中的数据传递之Parcelable接口
  4. Android(安卓)开发中使用 SQLite 数据库
  5. androdi与服务器Socket通信原理
  6. Android之Adapter用法总结
  7. Android之Adapter用法总结
  8. Android之Adapter用法总结
  9. 官方NotePad实例学习--ListActivity的使用

随机推荐

  1. java获取http:图片下载代码——android基
  2. Android(安卓)makefile 组织结构
  3. android 源码分享
  4. LEADTOOLS Android的入门使用方法
  5. Android(安卓)Fragment详解(四):管理Fragm
  6. Android(安卓)SDK Manager顺利下载
  7. android studio线性布局 LinearLayout
  8. as中Settings.gradle的配置
  9. Win10系统中怎么安装Android(安卓)Studio
  10. 升级Android(安卓)Studio3.0遇到Unable t