详解xamarin Android 实现ListView万能适配器
详解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 万能适配器的实例,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!