android-ViewList的通用ViewHold
在写ViewList的时候要写Adapter的时候,经常大量的代码都是差不多的。
1 ViewHold
2 if(convertView ==null ){}else{}
3 setTag
4 FIndElement 和 Set 等等
所以我想能不能写一个通用的ViewHold的和通用的Adapter呢?
我们来试试吧。
直接上代码,然后再进行分析。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20pt" /> <TextView android:id="@+id/context" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="15pt"/> </LinearLayout>
Bean数据结构
public class Bean { String context; String title; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContext() { return context; } public void setContext(String context) { this.context = context; } }
通用的ViewHold
import android.content.Context; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; /** * Created by sunfan on 15-4-19. * 通用的ViewHold类 */ public class CommonViewHold { private View mView;//当前页面 private SparseArray<View> elements = new SparseArray<View>();//控件元素 /** * 构造函数,当传入的convertView为null时对mView进行初始化,并设置tag * @param context * @param parent * @param resource */ private CommonViewHold(Context context, ViewGroup parent, int resource) { mView = LayoutInflater.from(context).inflate(resource,parent,false); mView.setTag(this); } /** * 获取 CommonViewHold对象,包含 mView和layout里已经添加elements的容器 * @param context * @param convertView * @param parent * @param resource * @return */ public static CommonViewHold getViewHold(Context context ,View convertView,ViewGroup parent,int resource){ if (convertView==null){ return new CommonViewHold(context,parent,resource); }else{ CommonViewHold viewHold = (CommonViewHold) convertView.getTag(); return viewHold; } } public View getView() { return mView; } /** * 维护一个element的容器,如果容器里存在此控件则直接读取,如果不存在则通过findAndSetElement找到元素后 * 写入容器中 * @param viewId * @param <T> * @return */ public <T extends View> T getElement(int viewId){ View view = elements.get(viewId); if(view == null){ view = mView.findViewById(viewId); elements.put(viewId,view); } return (T)view; } }
通用的adapter
import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import java.util.List; /** * Created by sunfan on 15-4-18. */ public abstract class CommonArrayAdapter<T> extends ArrayAdapter{ protected Context mContext;//当前上下文 protected int mResource;//item protected int mPosition;//当前位置 protected CommonViewHold viewHold;//ViewHold的引用 /** * 初始化 * @param context * @param resource * @param objects */ public CommonArrayAdapter(Context context, int resource, List objects) { super(context, resource, objects); this.mContext = context; this.mResource = resource; } @Override public View getView(int position, View convertView, ViewGroup parent) { this.mPosition = position; viewHold = CommonViewHold.getViewHold(mContext,convertView,parent,mResource); findAndSetElement(); return viewHold.getView(); } /** * 需要实现控件的获取与赋值过程 * 这里建议调用内部的viewhold对象里的获取控件的方法 * 例如 * TextView title = super.viewHold.getElement(R.id.title); title.setText(bean.getTitle()); */ public abstract void findAndSetElement(); }
客户端
import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.Window; import android.widget.ListView; import android.widget.TextView; import java.util.ArrayList; import java.util.List; public class MainActivity extends Activity { ListView listView; List<Bean> beans = new ArrayList<Bean>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); init(); listView = (ListView) findViewById(R.id.list_view); listView.setAdapter(new MyAdapter(this, R.layout.list_item, beans)); } /** * 实现CommonArrayAdapter的findAndSetElement方法 */ class MyAdapter extends CommonArrayAdapter<Bean> { public MyAdapter(Context context, int resource, List objects) { super(context, resource, objects); } @Override public void findAndSetElement() { TextView title = super.viewHold.getElement(R.id.title); TextView context = super.viewHold.getElement(R.id.context); Bean bean = beans.get(super.mPosition); title.setText(bean.getTitle()); context.setText(bean.getContext()); } } /* 初始化测试数据 */ private void init() { Bean b1 = new Bean(); b1.setTitle("title1"); b1.setContext("content1content1content1content1content1content1content1content1content1content1content1content1"); Bean b2 = new Bean(); b2.setTitle("title2"); b2.setContext("content2content2content2content2content2content2content2content2content2"); Bean b3 = new Bean(); b3.setTitle("title3"); b3.setContext("content3content3content3content3content3content3content3content3"); Bean b4 = new Bean(); b4.setTitle("title4"); b4.setContext("content4content4content4content4content4content4content4content4"); Bean b5 = new Bean(); b5.setTitle("title5"); b5.setContext("content5content5content5content5content5content5content5content5content5content5content5"); Bean b6 = new Bean(); b6.setTitle("title6"); b6.setContext("content6content6content6content6content6content6content6content6"); Bean b7 = new Bean(); b7.setTitle("title7"); b7.setContext("content7content7content7content7content7content7content7content7"); beans.add(b1); beans.add(b2); beans.add(b3); beans.add(b4); beans.add(b5); beans.add(b6); beans.add(b7); } }
--------------以上为全部代码----------------------
代码分析
整个代码的流程和结构
CommonViewHold 相比传统的Viewhold,他采用容器的方式存储元素,并且封装了客户端用来判断covertview为空的初始化操作
提供了一个存放元素的容器
private SparseArray<View> elements = new SparseArray<View>();//控件元素
当然他提供有获取容器的方法
/** * 维护一个element的容器,如果容器里存在此控件则直接读取,如果不存在则通过findAndSetElement找到元素后 * 写入容器中 * @param viewId * @param <T> * @return */ public <T extends View> T getElement(int viewId){ View view = elements.get(viewId); if(view == null){ view = mView.findViewById(viewId); elements.put(viewId,view); } return (T)view; }
然后就是做初始化的动作了。
convertView==null的时候的判断,这一段逻辑其实很简单,如果不为空就直接返回,为空就初始化。
private CommonViewHold(Context context, ViewGroup parent, int resource) { mView = LayoutInflater.from(context).inflate(resource,parent,false); mView.setTag(this); } /** * 获取 CommonViewHold对象,包含 mView和layout里已经添加elements的容器 * @param context * @param convertView * @param parent * @param resource * @return */ public static CommonViewHold getViewHold(Context context ,View convertView,ViewGroup parent,int resource){ if (convertView==null){ return new CommonViewHold(context,parent,resource); }else{ CommonViewHold viewHold = (CommonViewHold) convertView.getTag(); return viewHold; } }
通用的commonAdapter是一个模板类
public abstract class CommonArrayAdapter<T> extends ArrayAdapter
关键属性,当用户实现findAndSet的时候需要使用这个引用来获取控件
protected CommonViewHold viewHold;//ViewHold的引用
核心模板方法
@Override public View getView(int position, View convertView, ViewGroup parent) { this.mPosition = position; viewHold = CommonViewHold.getViewHold(mContext,convertView,parent,mResource); findAndSetElement(); return viewHold.getView(); }
需要用户去实现的方法
/** * 需要实现控件的获取与赋值过程 * 这里建议调用内部的viewhold对象里的获取控件的方法 * 例如 * TextView title = super.viewHold.getElement(R.id.title); title.setText(bean.getTitle()); */ public abstract void findAndSetElement();
直接从客户端可以看到,代码是十分便捷的,只需要一个内部类重写commonAdapter的findAndSet方法即可。
class MyAdapter extends CommonArrayAdapter<Bean> {
public MyAdapter(Context context, int resource, List objects) {
super(context, resource, objects);
}
@Override
public void findAndSetElement() {
TextView title = super.viewHold.getElement(R.id.title);
TextView context = super.viewHold.getElement(R.id.context);
Bean bean = beans.get(super.mPosition);
title.setText(bean.getTitle());
context.setText(bean.getContext());
}
}
调用也变得很轻松
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
init();
listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(new MyAdapter(this, R.layout.list_item, beans));
}
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。