使用过Java开发安卓App的童鞋肯定用过ListView,它灵活多变的设计方式与思路,对于我这样从Delphi转来的人而言,深有启迪。本文的忠旨是通过介绍Java中Adapter的用法,来让不了解这方面的童鞋学习其中的设计思想。
ListView是真正的数据与界面完全分离的设计思路,UI由Android标准的XML方式随意搭配,定制显式效果,这种UI设计思想,确实很先进。不过本文主要讲的是数据适配器(Adapter),所以UI方面下回有机会再说。
在Android开发中(java),每个ListView都有自己的Adapter。ListView要显示什么内容,完全由这个数据适配器控制。ADK为数据适配器规定了标准的接口BaseAdapter,它规定了需要用到的标准接口,我们在开发中,只需要继承(extends)BaseAdapter产生一个新类,就可以在里面写自己的代码了。下面我贴出一个基本的可以用来显示字符串列表的Adapter:
/** * 数据适配器 * @author YangYxd */ public class ListViewAdapter extends BaseAdapter{ protected LayoutInflater mInflater; private List<String> list; public ListViewAdapter(Context context, List<String> list) { this.mInflater = LayoutInflater.from(context); this.list = list; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ... return convertView; } }
上面的代码,是一个最简单的自定义Adapter,实现了最主要的接口:getCount()、getItem()、getItemId()和getView()。来看看这几个主要接口的作用:
- getCount():返回数据的行数。就是由它来控制ListView显示的数据一共有几条。
- getItem(): 获取一个Item。在使用lstView.getItemAtPosition(position)这样的功能时,会调用getItem()返回具体的数据。
- getItemId(): 获取一个Item的ID。和getItem()类似用途,只不过它一般用来返回数据的ID字段。实际开发中,往往直接返回position,也就是索引号。
- getView():这个是重中之重了。由它来指定ListView中每一行的数据到底怎么显示。下面我们详细的说说getView。
经常在自定义Adapter时,会有类似下面的getView():
/** 视图所有者 */ public static class ListViewHolder{ public TextView tvTitle; }
@Override public View getView(int position, View convertView, ViewGroup parent) { ListViewHolder holder = null; final String value = list.get(position); if (convertView != null && convertView.getTag() != null) holder = (ListViewHolder)convertView.getTag(); if (holder == null) { holder = new ListViewHolder(); convertView = mInflater.inflate(R.layout.lst_item_view, null); // 加载一个XML界面 holder.tvTitle = (LinearLayout) convertView.findViewById(R.id.tvTitle); // 得到tvTitle这个控件用于显示文本 convertView.setTag(holder); } holder.tvTitle.setText(value); return convertView; }
lst_item_view.xml:
<LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <TextView android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="4dp" android:layout_marginRight="8dp" android:background="@drawable/chatfrom_bg" /> </LinearLayout>
完成了ListViewAdapter,只需要new一个实例,然后
adapter = new ListViewAdapter(context); lstView.setAdapter(adapter);
这样,ListView就可以使用我们的数据适配器显示内容了。 上面的这段getView()代码还应用了缓存技术,避免每次都去加载XML和获取tvTitle。实际上在getView可以很复杂,比如Item不再是一个字符串,而是一个类,类中包含了各种数据,如大小,金额等。还可以根据不同的Item,返回不同的convertView,做出一个ListView显示多种效果的样子,如Android QQ的“我”栏目,上面是功能,下面是数据等。
除了ListView,在使用Java进行Android开发中,很多地方都用了数据适配器方式。数据与UI完全分离,让程序变得很灵活,UI部分不需要占用内存去存放数据,处理数据的代码也可以专心的处理数据而不去管UI怎么显示。在数据变化后,只需要适时的调用一下notifyDataSetChanged()函数界面就会更新显示了。
上面说了在Java中Adapter的基本功能与用法,玩Delphi的童鞋可能已经发现了,它和我们的ListBox将Style设置成lbVirtualOwnerDraw时原理差不多。不过ADK做的更加成熟,更加实用了。它的设计思想,很值得我们学习。