首页 > 代码库 > 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 }
显示效果