BaseExpandableListAdapter封装

    xiaoxiao2025-03-28  10

    一、需求分析

            每当我们使用到ExpandableListView的时候,基本都需要写一个适配器继承BaseExpandableListAdapter,其中有很多需要重写的方法,并且这部分代码也都是重复的,还有ViewHolder的重用代码,每次都要写一遍的话很繁琐,所以我们可以把这部分代码全部封装出来,然后子类只需要处理关键性的代码就行。

    二、具体实现

            我们知道BaseExpandableListAdapter通常会使用到两个布局文件和两个数据集合,数据的结构体一般不同因此我们应该需要用到两个泛型,还有这些参数应该是由外界传进来的。然后我们主要关心的就是getGroupView()方法和getChildView()方法,我们只需要预留两个抽象的转换方法给子类重写就行。

    import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import java.util.List; /** * 封装的BaseExpandableListAdapter类,抽离出公共代码 */ public abstract class MyBaseExpandableAdapter<P, C> extends BaseExpandableListAdapter { protected Context mContext; protected List<P> mParentList; protected List<List<C>> mChildList; protected int mParentLayout; protected int mChildLayout; /** * 参数过多,使用构造者模式? */ public MyBaseExpandableAdapter(Context mContext, List<P> mParentList, List<List<C>> mChildList, int parentLayout, int childLayout) { this.mContext = mContext; this.mParentList = mParentList; this.mChildList = mChildList; this.mParentLayout = parentLayout; this.mChildLayout = childLayout; } public abstract void convertParent(ViewHolder holder, P p, int groupPosition, boolean isExpanded); public abstract void convertChild(ViewHolder holder, C c, int groupPosition, int childPosition, boolean isLastChild); @Override public int getGroupCount() { return mParentList == null ? 0 : mParentList.size(); } @Override public int getChildrenCount(int groupPosition) { return (mChildList == null || mChildList.size() <= groupPosition || mChildList.get(groupPosition) == null) ? 0 : mChildList.get(groupPosition).size(); } @Override public Object getGroup(int groupPosition) { return mParentList == null ? null : mParentList.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { return (mChildList == null || mChildList.size() <= groupPosition || mChildList.get(groupPosition) == null) ? null : mChildList.get(groupPosition).get(childPosition); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public boolean hasStableIds() { return false; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { ViewHolder holder = ViewHolder.getInstance(mContext, convertView, mParentLayout); convertParent(holder, mParentList.get(groupPosition), groupPosition, isExpanded); return holder.getConvertView(); } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { ViewHolder holder = ViewHolder.getInstance(mContext, convertView, mChildLayout); convertChild(holder, mChildList.get(groupPosition).get(childPosition), groupPosition, childPosition, isLastChild); return holder.getConvertView(); } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; // 子列表可以点击 } } 这里用到了一个ViewHolder类,我把它单独抽出来了,你也可以把ViewHolder类作为一个静态内部类放在MyBaseExpandableAdapter类中。 import android.content.Context; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; /** * 适配器通用的ViewHolder,而且 BaseAdapter 和 BaseExpandableListAdapter 都可以用 */ public class ViewHolder { private View convertView; private SparseArray<View> views; // SparseArray效率比HashMap更高 private ViewHolder(View convertView) { this.views = new SparseArray<>(); this.convertView = convertView; convertView.setTag(this); } public static ViewHolder getInstance(Context context, View convertView, int layout) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate(layout, null); return new ViewHolder(convertView); } return (ViewHolder) convertView.getTag(); // 重用convertView的逻辑 } public <T extends View> T findViewById(int id) { View view = views.get(id); if (view == null) { view = convertView.findViewById(id); views.append(id, view); } return (T) view; } public View getConvertView() { return convertView; } } 三、使用实例

            好了,有了上面两个类就可以使用了,这里我直接搬运一个项目中的使用实例过来,具体的bean类就不贴了

    public class TodaySignAdapter extends MyBaseExpandableAdapter<SignGroup, Record> { public TodaySignAdapter(List<List<Record>> childLists, List<SignGroup> parentList, Context context) { super(context, parentList, childLists, R.layout.expandable_list_today_group, R.layout.expandable_list_today_child); } @Override public void convertParent(ViewHolder holder, SignGroup signGroup, int groupPosition, boolean isExpanded) { ImageView groupArrow = holder.findViewById(R.id.iv_group_arrow); ImageView groupImage = holder.findViewById(R.id.iv_sign_group); TextView signInfo = holder.findViewById(R.id.tv_sign_info); TextView locationName = holder.findViewById(R.id.tv_sign_location_name); signInfo.setText("打卡" + signGroup.signCount + "次/" + signGroup.duration); locationName.setText(signGroup.locationName); groupArrow.setImageResource(isExpanded ? R.mipmap.arrow_o : R.mipmap.arrow_n); ImageLoader.getInstance().displayImage(URLs.HEAD_URL + signGroup.fileName, groupImage); } @Override public void convertChild(ViewHolder holder, Record record, int groupPosition, int childPosition, boolean isLastChild) { ImageView childImage = holder.findViewById(R.id.iv_sign_file_name); TextView dateSign = holder.findViewById(R.id.tv_sign_date); ImageLoader.getInstance().displayImage(URLs.HEAD_URL + record.getFileName(), childImage); dateSign.setText(TimeTransferUtil.getTime(Long.parseLong(record.getDateSign()))); } }

    在对应的convertParent()和convertChild()方法中分别先获取控件然后初始化数据即可,省去了大部分重复的代码逻辑。

    四、扩展,BaseApater的封装

    import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import java.util.List; public abstract class MyBaseAdapter<T> extends BaseAdapter { protected Context mContext; protected List<T> mList; // 数据 protected int mLayout; // 布局id public MyBaseAdapter(Context context, List<T> list, int layout) { this.mContext = context; this.mList = list; this.mLayout = layout; } @Override public int getCount() { return mList == null ? 0 : mList.size(); } @Override public Object getItem(int position) { return mList == null ? null : mList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = ViewHolder.getInstance(mContext, convertView, mLayout); convert(holder, mList.get(position), position); return holder.getConvertView(); } public abstract void convert(ViewHolder holder, T t, int position); }其中ViewHolder和上述的是同一个。我之前也有一篇博客是说的这个BaseAdapter的封装,ViewHolder是作为静态内部类放在封装的类中的,还附有一个比较详细的使用实例,有兴趣的可以去看看

    http://blog.csdn.net/afei__/article/details/51502134

    转载请注明原文地址: https://ju.6miu.com/read-1297470.html
    最新回复(0)