xamarin android 打造ListView万能适配器

版权声明:本文为博主原创文章,未经博主允许转载随意。 https://blog.csdn.net/kebi007/article/details/77101947

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

本章主要分为以下三点:

  1. 打造通用的ViewHolder优化ListView性能
  2. 使用泛型Adapter适应不同布局的ListView
  3. 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;

作者:张林
标题:xamarin android 打造ListView万能适配器
原文地址:http://blog.csdn.net/kebi007/article/details/77101947
转载随意注明出处

猜你喜欢

转载自blog.csdn.net/kebi007/article/details/77101947