#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。
如果有特殊需求可以自己进行简单修改。
#共勉:认准并发挥自己的特长,就有机会成功。