我们在安卓开发过程中,ListView进行数据绑定要通过Adapter,一般的做法是我们要新建一个ListViewActivity,再对应新建一个Adabper继承自BaseAdapter,并实现其中的一些方法,在GetView方法中查找控件并绑定数据。ListView在安卓开发中非常常见,如果一个app有20个ListView,那么就需要20个Adapter。这样产生大量重复繁重的工作。因此产生了做一个通用Adapter的想法,避免创建多个Adapter文件,编写重复代码。
今早看到慕课网有一篇视频 安卓打造万能适配器 介绍了java方式实现方法。因此我参照java的方式实现了使用xamarin C#打造的万能适配器。主要利用了C#的事件机制和泛型特性。代码如下:
/// <summary>
/// 通用适配器
/// </summary>
/// <typeparam name="T"></typeparam>
public class CommonAdapter<T> : BaseAdapter<T>
{
//要绑定的数据
List<T> items;
//页面上下文
Activity context;
//ListViewItem的布局id
int layoutId;
public delegate View GetViewEvent(int position, View convertView, ViewGroup parent, T item, ViewHolder viewHolder);
/// <summary>
/// 加载item的View事件
/// </summary>
public event GetViewEvent OnGetView;
public CommonAdapter(Activity context, int layoutId, List<T> items)
: base()
{
this.context = context;
this.layoutId = layoutId;
this.items = items;
}
public override T this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];
View view = convertView;
ViewHolder viewHolder = ViewHolder.Get(context, convertView, parent, this.layoutId, position);
if (this.OnGetView != null)
return this.OnGetView(position, convertView, parent, item, viewHolder);
return view;
}
}
/// <summary>
/// 通用ViewHolder
/// </summary>
public class ViewHolder : Java.Lang.Object
{
private SparseArray<View> views;
int position;
View ConvertView;
public ViewHolder(Activity context, ViewGroup parent, int layoutID, int position)
{
this.position = position;
this.views = new SparseArray<View>();
ConvertView = context.LayoutInflater.Inflate(layoutID, null);
ConvertView.Tag = this;
//comConvertView.SetTag(
}
//单例模式获取对象实例
public static ViewHolder Get(Activity context, View convertView, ViewGroup parent, int layoutID, int position)
{
if (convertView == null)
return new ViewHolder(context, parent, layoutID, position);
else
{
ViewHolder holder = (ViewHolder)convertView.Tag;
holder.position = position;
return holder;
}
}
public View GetConvertView()
{
return ConvertView;
}
/// <summary>
/// 通过ViewID获取控件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="viewId"></param>
/// <returns></returns>
public T GetView<T>(int viewId) where T : View
{
View view = views.Get(viewId);
if (view == null)
{
view = ConvertView.FindViewById<T>(viewId);
views.Put(viewId, view);
}
return (T)view;
}
}
如何使用呢?首先创建通用Adapter的对象,传入必要参数。
Vito.PhoneControl.Adapter.CommonAdapter<Models.MainButton> comAdapter =
new PhoneControl.Adapter.CommonAdapter<Models.MainButton>(this, Resource.Layout.MainBlandGridItem, items);
实现通用Adapter里面注册的事件:
comAdapter.OnGetView += comAdapter_OnGetView;
//事件方法实现:
View comAdapter_OnGetView(int position, View convertView, ViewGroup parent, Models.MainButton item, PhoneControl.Adapter.ViewHolder viewHolder)
{
//通过ViewHolder获取对象并赋值
viewHolder.GetView<TextView>(Resource.Id.textViewModeName).Text = item.Text;
var imageView = viewHolder.GetView<SquareImageView>(Resource.Id.SquareImageModelICOPath);
imageView.SetImageResource(item.ImageID);
return viewHolder.GetConvertView();
}
最后将通用Adapter对象赋值给ListView的Adapter属性:
Listview.Adapter = comAdapter;
这样我们不需要新建Adapter类就实现了对ListView的数据绑定,精简了大量代码。