首页 > 代码库 > Android技术18:Android中Adapter类详解

Android技术18:Android中Adapter类详解

1.Adapter设计模式 

    Android中adapter接口有很多种实现,例如,ArrayAdapter,BaseAdapter,CursorAdapter,SimpleAdapter,SimpleCursorAdapter等,他们分别对应不同的数据源。例如,ArrayAdater对应List和数组数据源,而CursorAdapter对应Cursor对象(一般从数据库中获取的记录集)。这些Adapter都需要getView方法返回当前列表项显示的View对象。当Model发生改变时,会调用BaseAdapter.notifyDataSetChanged方法通知组件数据已经改变,这时Adapter会调用getView方法用于重新显示组件中的内容。当组件中显示的数据变化时,如删除一个项表项,组件回调Adapter中getView方法用于重新显示组件中的内容。当组件中显示的数据变化时,如删除一个项表项,组件会通知Adapter中方法删除Model中相应的记录,然后再调用BaseAdapter.notifyDataSetChanged方法使组件中显示数据发生变化。总之一句话,无论数据变化还是组件显示数据发送变化,都需要将Adpter作为桥梁来达到View和Model之间同步的目的。

      Android中Adapter是非常明显的MVC模式。

2.Adapter内部实现原理

下面我们以ListView和BaseAdapter为例,说明其原理。

原理:ListView中List的每个item,向adapter请求一个视图View,然后Adapter中getView方法创建一个新的或从缓存区中获取View修改ViewHoler内容,然后显示。Android中为我们提供了View缓存并不是每个新的item需要新建一个新视图,Android中通过有个叫做Recycler的构件实现。

通过上图可知,AndroidListView只在刚开始convertView为空时,才创建新的View。这既减轻了内存的压力,又提高的ListView滑动时的更新的性能和用户体验。

3.代码演示

ListView+BaseAdapter,MyAdaoter继承BaseAdapter,实现其方法,关键在getView()。

 1 class MyAdapter extends BaseAdapter{ 2  3         private List<Map<String,String>> datas=new ArrayList<Map<String,String>>(); 4         private LayoutInflater mInflater;  5         private static final int TYPE_ITEM = 0;   6         private static final int TYPE_SEPARATOR = 1;   7         private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;   8         private TreeSet mSeparatorsSet = new TreeSet();   9          10         public MyAdapter() {11             mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);  12         }13         //添加项目14         public void add(Map<String,String> item){15             datas.add(item);16             notifyDataSetChanged();17         }18         //添加分割栏19         public void addSeparator(Map<String,String> item){20             datas.add(item);21             mSeparatorsSet.add(datas.size()-1);22             notifyDataSetChanged();23         }24         @Override25         public int getItemViewType(int position) {26             return mSeparatorsSet.contains(position)?TYPE_SEPARATOR:TYPE_ITEM;27         }28         29         @Override30         public int getViewTypeCount() {31             return TYPE_MAX_COUNT;32         }33         @Override34         public int getCount() {35             return datas.size();36         }37 38         @Override39         public Object getItem(int position) {40         41             return datas.get(position);42         }43 44         @Override45         public long getItemId(int position) {46             47             return position;48         }49 50         @Override51         public View getView(int position, View convertView, ViewGroup parent) {52             View view=convertView;53             int type=getItemViewType(position);54             ViewHolder viewHolder=null;55             ViewHolder1 viewHolder1=null;56             if(view==null){57                 if(type==TYPE_ITEM){58                     59                     view=mInflater.inflate(R.layout.item1, null);60                     viewHolder=new ViewHolder();61                     viewHolder.textview1=(TextView) view.findViewById(R.id.title);62                     viewHolder.textview2=(TextView) view.findViewById(R.id.num);63                     view.setTag(viewHolder);//View中的setTag(Onbect)表示给View添加一个格外的数据,以后可以用getTag()将这个数据取出来。64                 }else{65                     view=mInflater.inflate(R.layout.item2, null);66                     viewHolder1=new ViewHolder1();67                     viewHolder1.textview1=(TextView)view.findViewById(R.id.title);68                     view.setTag(viewHolder1);69                 }70             }71             72             if(type==TYPE_ITEM){73                 viewHolder=(ViewHolder) view.getTag();74                 viewHolder.textview1.setText(datas.get(position).get("title"));75                 viewHolder.textview2.setText(datas.get(position).get("num"));76             }else{77                 viewHolder1=(ViewHolder1) view.getTag();78                 viewHolder1.textview1.setText(datas.get(position).get("title"));79                 view.setBackgroundColor(Color.BLUE);80             }81             return view;82         }83             84     }
1 public static class ViewHolder{2         public TextView textview1;3         public TextView textview2;4 }5     6 public static class ViewHolder1{7         public TextView textview1;8 }

ViewHolder,ViewHolder1分别对应两种不同视图,一种item,一种分割栏

item1.xml

 1 <LinearLayout 2      xmlns:android="http://schemas.android.com/apk/res/android" 3      android:layout_width="fill_parent" 4      android:layout_height="fill_parent" 5      android:padding="10dip"> 6      7     <TextView  8         android:id="@+id/title" 9         android:layout_width="fill_parent"10         android:layout_height="wrap_content"11         android:gravity="left"12         android:textSize="18sp"13         android:layout_weight="1"/>14     <TextView 15         android:id="@+id/num"16         android:layout_width="fill_parent"17         android:layout_height="wrap_content"18         android:gravity="center_horizontal"19         android:textSize="18sp"20         android:layout_weight="1"/>21 </LinearLayout>

item2.xml

 1 <LinearLayout 2      xmlns:android="http://schemas.android.com/apk/res/android" 3      android:layout_width="fill_parent" 4      android:layout_height="fill_parent"> 5      6     <TextView  7         android:id="@+id/title" 8         android:gravity="left" 9         android:textSize="22sp"10         android:background="#BCD2EE"11         android:layout_width="fill_parent"12         android:layout_height="wrap_content"13         android:padding="5dip"14     />15 16 </LinearLayout>

初始化数据

 1 private void init(MyAdapter adapter){ 2         Map<String,String> map=null; 3         for(int i=0;i<100;i++){ 4             if(i%5!=0){ 5             map=new HashMap<String, String>(); 6             map.put("title", "title"+i); 7             map.put("num", "num"+i); 8             adapter.add(map); 9             }else{10                 map=new HashMap<String, String>();11                 map.put("title", "S"+i/5);12                 adapter.addSeparator(map);13             }14         }15     }

显示效果