#Android Adapter的封装类CommonAdaper
Android程序基本都是要用到ListView来显示数据,而ListView的显示必须要使用Adapter。
之前也写过几次BaseAdapter的封装类,但是这次这个封装类比之前任何一个都好用一些。
##一.先看效果:
##二.再看代码用法:
###1.MainActivity的代码:
package com.liwenzhi.asr.commonadapterdemo; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener { ListView listView; DeveloperAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); initEvent(); } private void initView() { listView = findViewById(R.id.listView); } private void initData() { String[] items = {"开发者选项", "内存", "提交错误报告", "桌面备份密码", "不锁定屏幕"}; adapter = new DeveloperAdapter(items); listView.setAdapter(adapter); } private void initEvent() { listView.setOnItemClickListener(this); } //ListView的条目点击事件 @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { } }
###2.DeveloperAdaperd的代码
package com.liwenzhi.asr.commonadapterdemo; import android.view.View; import android.widget.ImageView; import android.widget.Switch; import android.widget.TextView; import java.util.List; public class DeveloperAdapter extends CommonAdapter<String> {//可以传入List的Bean类 //构造方法自己定义,可以传入集合,数组,上下文。。。 public DeveloperAdapter(List<String> list) { super(list); } public DeveloperAdapter(String[] list) { super(list); } //必须要重写的方法1,传入Item的布局 @Override public int setLayoutRes() { return R.layout.item_developer; } //必须要重写的方法2,设置Item里面的数据显示 @Override public void setData(CommonAdapter.ViewHolder holder, String data) {//这里的data是position对应的集合的数据,相当于getItem的数据 //设置数据 TextView tv_item_title = holder.getView(R.id.tv_item_title); tv_item_title.setText(data); //获取position动态改变图标 int position = holder.getPosition(); Switch switch_item = holder.getView(R.id.switch_item); ImageView iv_item = holder.getView(R.id.iv_item); //选择性显示图标 if (position == 0 || position == 4) { switch_item.setVisibility(View.VISIBLE); iv_item.setVisibility(View.GONE); } } }
###3.最后看一下这个CommonAdapter的封装类代码:
package com.liwenzhi.asr.commonadapterdemo; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import java.util.Arrays; import java.util.List; /** * 此类为listview adpter封装基类,用户继承此类后,必须实现此类中两个抽象方法, * 其他方法可根据需求决定是否重写 */ public abstract class CommonAdapter<T> extends BaseAdapter { protected List<T> mData; //传入数组 public CommonAdapter(T[] data) { mData = Arrays.asList(data); } //传入集合 public CommonAdapter(List<T> data) { mData = data; } @Override public int getCount() { return mData == null ? 0 : mData.size(); } @Override public Object getItem(int position) { return mData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = ViewHolder.getHolder(convertView, parent, position, setLayoutRes()); setData(holder, mData.get(position)); return holder.getConvertView(); } public static class ViewHolder { //被点击的当前位置 private int position; //用一个map集合来保存每个控件的id,这个SparseArray是android提供的一个比map使用效率更高的一个 //集合,但是局限是,key只能是int类型,所以当键值对涉及到key是int类型时,可以优先考虑使用这个集合 private SparseArray<View> array; //复用的布局 private View convertView; public ViewHolder() { } //带三个构造的方法,这里将构造方法私有,防止外界去创建,通过自身的静态方法去创建对象即可 private ViewHolder(ViewGroup parent, int position, int layout) { this.position = position; //每次创建对象,就将布局解析出来 convertView = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false); //然后将对象保存到convertView对应的setTag中,方便每次该获取 convertView.setTag(this); array = new SparseArray<>(); } public static ViewHolder getHolder(View convertView, ViewGroup parent, int position, int layout) { //每次判断converView是否为空,如果为空就直接返回这个创建的对象 if (convertView == null) { return new ViewHolder(parent, position, layout); } else { //不为空的情况,就跟我们上面的代码一样,每次通过复用的控件拿到对应的ViewHolder对象 ViewHolder holder = (ViewHolder) convertView.getTag(); //这里一定要更新下下标的位置,虽然对象相同,但是我们每次都要更新现有的位置, holder.position = position; //返回已经创建好的holder对象 return holder; } } /** * 这个方法是通过控件id拿到对应的控件 */ public <T extends View> T getView(int viewId) { //每次通过viewId键去拿到到对应的控件 View view = array.get(viewId); //如果为空,表示该集合中还没有存入该控件 if (view == null) { //先要去通过converView拿到控件id view = convertView.findViewById(viewId); //保存到集合中,以便下次直接获取 array.put(viewId, view); } //返回View的子类控件,采用泛型的方便是不需要强制转换了 return (T) view; } //得到convertView布局 public View getConvertView() { return convertView; } public int getPosition() { return position; } } /** * 实现此方法,返回具体的item布局资源ID */ public abstract int setLayoutRes(); /** * 实现此方法,需要获取item子控件,并且为每一个控件设置数据 * * @param holder 基类返回的holder,通过holder的getView方法可以获取item中的子控件 * @param t 数据对象的泛型,继承此类后,泛型类型确定 */ public abstract void setData(ViewHolder holder, T t); }
上面的CommonAdapter已经高度封装了BaseAdapter,不需要自己写ViewHolder。
如果有特殊需求可以自己进行简单修改。
#共勉:认准并发挥自己的特长,就有机会成功。