首页 > 系统 > Android > 正文

详解xamarin Android 实现ListView万能适配器

2019-12-12 02:14:29
字体:
来源:转载
供稿:网友

详解xamarin Android 实现ListView万能适配器

早些时候接触xamarin Android 的列表,写了很多ListView的Adapter,建一个ListView就写一个Adapter,每一个Adapter里面还有去写一个ViewHolder的类来优化,自从看了hongyang博客的listview万能适配器的文章,学习良多,所以就写篇关于xamarin android ListView通用适配器的文章。

本章主要分为以下三点:

  • 打造通用的ViewHolder优化ListView性能
  • 使用泛型Adapter适应不同布局的ListView
  • C#委托和Java匿名内部类的比较

打造通用的ViewHolder优化ListView性能

 public class ViewHolder:Java.Lang.Object  {    private SparseArray<View> Views;     View ConvertView;    private Context context ;     int mPosition;    private ViewHolder(Context _context,ViewGroup parent ,int itemLayoutId,int position)    {      this.mPosition = position;      Views = new SparseArray<View>();      ConvertView = LayoutInflater.From(_context).Inflate(itemLayoutId,null);      ConvertView.Tag = this;    }    public static ViewHolder Get(Context context , View convertView,ViewGroup parent ,int itemLayoutId,int position)    {      if (convertView == null)      {        return new ViewHolder(context, parent, itemLayoutId, position);      }      else      {        ViewHolder holder = (ViewHolder)convertView.Tag;        holder.mPosition = position;        return holder;      }    }    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;    }    public View GetConvertView()    {      return ConvertView;    }    /// <summary>    /// 给TextView 设置文本    /// </summary>    /// <param name="viewId"></param>    /// <param name="text"></param>    /// <returns></returns>    public ViewHolder SetText(int viewId ,string text)    {      TextView view = GetView<TextView>(viewId);      view.Text = text;      return this;    }    /// <summary>    /// 给ImageView 设置图片    /// </summary>    public ViewHolder SetImageBitMap(int viewId , Bitmap bm)    {      ImageView view = GetView<ImageView>(viewId);      view.SetImageBitmap(bm);      return this;    }  }

稍微解释一下:

ViewHolder的构造方法中初始化变量,并将ListView的布局view的Tag设置成viewholder的实例
Get方法使用单例模式初始化ViewHolder
GetView泛型方法获取ListView布局中的空间
SetText、SetImageBitMap给一些常用的控件复值

使用泛型Adapter适应不同布局的ListView

CommonAdapter是一个泛型的基类,一些重复的重写方法都在这个基类,然后我们写一个子类继承这个CommonAdapter,就简化了很多代码

 public abstract class CommonAdapter<T> :BaseAdapter  {    Context mContext;     List<T> mData;     int mItemLayoutId;    public CommonAdapter(Context context, List<T> data, int itemLayoutId):base()    {      this.mContext = context;      mData = data;      mItemLayoutId = itemLayoutId;    }    public override int Count    {      get      {        return mData.Count;      }    }    public override Java.Lang.Object GetItem(int position)    {      return null;    }    public override long GetItemId(int position)    {      return position;    }    public override View GetView(int position, View convertView, ViewGroup parent)    {      var item = mData[position];      ViewHolder viewHolder = ViewHolder.Get(mContext, convertView, parent, mItemLayoutId, position);      convert(viewHolder,mData[position]);      System.Diagnostics.Debug.Write(position);      return viewHolder.GetConvertView();    }    public abstract void convert(ViewHolder helper, T item);    public ViewHolder GetViewHolder(int position, View convertView, ViewGroup parent)    {      return ViewHolder.Get(mContext, convertView, parent, mItemLayoutId, position);    }  }

写一个newsAdapter继承CommonAdapter,只需要将赋值的代码写在重写方法convert里面极客,这样就简化了很多的代码

 public class NewsAdapter<T> : CommonAdapter<T>  {    public NewsAdapter(Context context, List<T> data, int resId) : base(context, data, resId)    {    }    public override void convert(ViewHolder helper, T item)    {      NewsViewModel model = (NewsViewModel)Convert.ChangeType(item, typeof(NewsViewModel));      helper.SetText(Resource.Id.tv_news_title, model.Title);      helper.SetText(Resource.Id.tv_news_id, model.NewsID.ToString());      helper.SetText(Resource.Id.tv_news_desc, model.Desc);    }  }

C#委托和Java匿名内部类的比较

看来上面的例子,虽然简化了很多代码,但是每个ListView还是得新建一个Adapter,看来hongyang大神的博客在java中用匿名内部类实现一个Adapter万能通用,但是c#中没有匿名内部内的概念,这就尴尬了。。。。。

c#中虽然没有这种概念,但语言是相通的,但是委托可以实现。万能通用的adapter代码如下:

 public class Common1Adapter<T> : BaseAdapter  {    Context mContext;    List<T> mData;    int mItemLayoutId;    public delegate View GetViewEvent(int position, View convertView, ViewGroup parent, T item, ViewHolder viewHolder);    public event GetViewEvent OnGetView;    public Common1Adapter(Context context, List<T> data, int itemLayoutId) : base()    {      this.mContext = context;      mData = data;      mItemLayoutId = itemLayoutId;    }    public override int Count    {      get      {        return mData.Count;      }    }    public override Java.Lang.Object GetItem(int position)    {      return null;    }    public override long GetItemId(int position)    {      return position;    }    public override View GetView(int position, View convertView, ViewGroup parent)    {      var item = mData[position];      ViewHolder viewHolder = ViewHolder.Get(mContext, convertView, parent, mItemLayoutId, position);      if (OnGetView != null)        return this.OnGetView(position,convertView,parent,item,viewHolder);      return convertView;    }  }}

在使用时,只需要在Activity中注册OnGetView 事件,这样多个ListView的Adapter就只需要一个通用的Adapter就行了

View OnGetView(int position,View convertView,ViewGroup parent,NewsViewModel model,ViewHolder viewHolder)    {      viewHolder.SetText(Resource.Id.tv_news_title, model.Title);      viewHolder.SetText(Resource.Id.tv_news_id, model.NewsID.ToString());      viewHolder.SetText(Resource.Id.tv_news_desc, model.Desc);      return viewHolder.GetConvertView();    }  List<NewsViewModel> list_news = new List<Adaptes.NewsViewModel>() {        new Adaptes.NewsViewModel () { NewsID =1,Title="测试标题124578cdascdas",Desc ="测acdsdas试内内容10c2da4s内容10c2da4s内容10c2da4s容10c2da4sc5das4cdas"},        new Adaptes.NewsViewModel () { NewsID =2,Title="cascascda24578cdascdas",Desc ="测dasc试内容10c2da4s内容10c2da4s内容10c2da4s内容10c2da4sc5das4cdas"},      };      Common1Adapter<NewsViewModel> adapter = new Adaptes.Common1Adapter<Adaptes.NewsViewModel>(this, list_news, Resource.Layout.item_listview_news);      adapter.OnGetView += OnGetView;      lv_news.Adapter = adapter;

以上就是Android listview 万能适配器的实例,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表