使用过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做的更加成熟,更加实用了。它的设计思想,很值得我们学习。
