Android适配器之基于BaseAdapter定义AbslistView万能适配器

为统一数据相关操作,现给出数据处理相关操作的接口定义,其中包含对列表数据的增删改查等常规操作。

/** * Created by Administrator on 2016/4/19. * 适配器的数据修改方法的定义 */public interface IAdapterDataModifyHelper<T> {    /**     * 通知适配器更新界面     *     * @param INotifyDataSetChange*/void setNotifyAdapterDataSetChange(INotifyAdapterDataSetChange INotifyDataSetChange);

/**     * 获取数据集     *     * @return*/List<T> getDataResources();

/**     * 设置数据集     *     * @param dataResources*/void setDataResource(T... dataResources);

    void setDataResource(List<? extends T> dataResource);

/**     * 添加数据     *     * @param location* @param dataResources*/void addDataResource(int location, T... dataResources);

    void addDataResource(int location, List<? extends T> dataResources);

    void addFirstDataResource(T... dataResources);

    void addFirstDataResource(List<T> dataResources);

    void addEndDataResource(T... dataResources);

    void addEndDataResource(List<T> dataResources);

/**     * 修改元素     *     * @param position* @param enity*/void reviseDataResource(int position, T enity);

/**     * 移除指定元素     */void removeDataResource(T removedEntiy);

/**     * 移除指定位置的元素     *     * @param position*/void removeDataResourceOnPosition(int position);

/**     * 清空所有数据集     */void clear();

/**     * 修正带操作的数据索引下标     *     * @param location* @return*/int proofOperateDataLocation(int location);

/**     * 判断操作的location位置是否正确     *     * @return*/boolean isOperateLocationRight(int position);}

IAdapterDataModifyHelper的实现类DataModifyHelper的部分源码如下:

/** * @Description:针对数据的相关处理Helper类* @author: Xiaoxuan948 * @date: 2016/7/20 20:37 */public class DataModifyHelper<T> implements IAdapterDataModifyHelper<T> {    private final UtilsLog lg = UtilsLog.getLogger(DataModifyHelper.class);    protected List<T> mDataResources;    private INotifyAdapterDataSetChange INotifyDataSetChange;

    public DataModifyHelper() {        this.mDataResources = new ArrayList<>();}

    @Overridepublic void setNotifyAdapterDataSetChange(INotifyAdapterDataSetChange INotifyDataSetChange) {        this.INotifyDataSetChange = INotifyDataSetChange;}

    @Overridepublic List<T> getDataResources() {        return mDataResources;}

    @Overridepublic void setDataResource(List<? extends T> setDataResources) {        /*针对集合空数据进行处理*/if (UtilsCollections.isCollectionNotEmpty(setDataResources) && setDataResources.contains(null)) {            lg.e("setDataResource集合包含null数据");setDataResources = Lists.newArrayList(Collections2.filter(setDataResources, new Predicate<T>() {                @Overridepublic boolean apply(T input) {                    return input != null;}            }));}        if (!UtilsCollections.isCollectionNotEmpty(setDataResources)) {            return;}        /*针对类型不匹配进行处理*/this.mDataResources = Lists.transform(setDataResources, new Function<Object, T>() {            @Overridepublic T apply(Object input) {                return (T) input;}        });INotifyDataSetChange.notifyAdapter();}

    @Overridepublic void addDataResource(int location, List<? extends T> addDataResources) {        if (UtilsCollections.isCollectionNotEmpty(addDataResources) && addDataResources.contains(null)) {            lg.e("addDataResource集合包含null数据");addDataResources = Lists.newArrayList(Collections2.filter(addDataResources, new Predicate<T>() {                @Overridepublic boolean apply(T input) {                    return input != null;}            }));}        if (!UtilsCollections.isCollectionNotEmpty(addDataResources)) {            lg.e("addDataResource:待加入的集合为空");            return;}        location = proofOperateDataLocation(location);        this.mDataResources.addAll(location, addDataResources);INotifyDataSetChange.notifyAdapter();}

    @Overridepublic void reviseDataResource(int position, T enity) {        if (isOperateLocationRight(position)) {            this.mDataResources.set(position, enity);INotifyDataSetChange.notifyAdapter();} else {            lg.e("reviseDataResource failed because position out of size " + this.mDataResources.size());}    }

    @Overridepublic void removeDataResourceOnPosition(int position) {        this.mDataResources.remove(position);INotifyDataSetChange.notifyAdapter();}

    @Overridepublic void clear() {        this.mDataResources.clear();INotifyDataSetChange.notifyAdapter();}

    @Overridepublic boolean isOperateLocationRight(int position) {        return !(position < 0 || position > this.mDataResources.size());}

    @Overridepublic int proofOperateDataLocation(int location) {        int newLocation = location < 0 ? 0 : location > this.mDataResources.size() ? this.mDataResources.size() : location;lg.e("proofOperateDataLocation from " + location + " to " + newLocation);        return newLocation;}}

观察可知,在DataModifyHelper构造函数中实例化mDataResources对象,其对应于列表控件中显示的数据。

setNotifyAdapterDataSetChange为外界提供数据更新的接口注入方法,在数据修改后调用INotifyDataSetChange的notifyAdapter()方法即可通知适配器更新。

setDataResource方法中,针对List数据先进行非空过滤,再判断List非空后进行数据修改,以确保mDataResources集合始终非空。这里会注意到其参数使用无限制通配符,这里是提高程序扩展性,当适配器基于接口编程时能方便set数据。(提示:List<Child>无法转为List<Parent>)

addDataResource的实现过程同setDataResource基本一致,都是针对数据集进行非空等一系列处理。

接下来考虑定义BaseAdapter抽象基类,抽取共性部分,即实现getCount、getItem、getItemId

观察源码可知,在构造函数中实例化DataModifyHelper对象,该对象负责数据的增删改查等操作。适配器中提供getDataModifyHelper方法,供外界获得操作数据的DataModifyHelper帮助类。

public abstract class AbsUnityBaseAdapter<T> extends BaseAdapter implements INotifyAdapterDataSetChange {    private static final UtilsLog lg = UtilsLog.getLogger(AbsUnityBaseAdapter.class);    private LayoutInflater layoutInflater;    private IAdapterDataModifyHelper<T> IAdapterataModifyHelper;

/**     * 构造方法     */protected AbsUnityBaseAdapter() {        this.IAdapterataModifyHelper = new DataModifyHelper<>();}

    public IAdapterDataModifyHelper<T> getDataModifyHelper() {        this.IAdapterataModifyHelper.setNotifyAdapterDataSetChange(this);        return IAdapterataModifyHelper;}

    @Overridepublic void notifyAdapter() {        notifyDataSetChanged();}

    /**     * default method     */@Overridepublic int getCount() {        return IAdapterataModifyHelper.getDataResources().size();}

    @Overridepublic T getItem(int position) {        //可能数组越界if (position >= IAdapterataModifyHelper.getDataResources().size()) {            lg.e("getItem:index " + position + " is out of size " + IAdapterataModifyHelper.getDataResources().size());            return null;}        return IAdapterataModifyHelper.getDataResources().get(position);}

    @Overridepublic long getItemId(int position) {        return position;}

    @Overridepublic View getView(int position, View convertView, ViewGroup parent) {        UnityAdapterViewHolder helper = null;        if (convertView != null) {            helper = (UnityAdapterViewHolder) convertView.getTag();} else {            if (layoutInflater == null) {                layoutInflater = LayoutInflater.from(parent.getContext());}            helper = new UnityAdapterViewHolder(layoutInflater, getLayoutId(), parent);}        convert(IAdapterataModifyHelper.getDataResources().get(position), helper, position);        return helper.getConvertView();}

    /*自定义抽象方法*/public abstract void convert(T itemEntity, UnityAdapterViewHolder helper, int position);

    public abstract int getLayoutId();}

分析getView部分源码可知,其基于UnityAdapterViewHolder类封装ViewHolder模式,构造方法如下:

/** * Created by Administrator on 2015/8/25. */public class UnityAdapterViewHolder {    private SparseArray<View> views;    private View convertView;

    public UnityAdapterViewHolder(LayoutInflater layoutInflater, int layoutId, ViewGroup parent) {        this.views = new SparseArray<>();        this.convertView = layoutInflater.inflate(layoutId, parent, false);        this.convertView.setTag(this);}

    public View getConvertView() {        return convertView;}

    /**     * generateView     *     * @param viewId* @param <T>* @return*/protected <T extends View> T generateView(int viewId) {        View view = views.get(viewId);        if (view == null) {            view = convertView.findViewById(viewId);views.put(viewId, view);}        return (T) view;}

    /**     * @param viewId* @param clz* @param <T>* @return*/public <T extends View> T generateView(int viewId, Class<T> clz) {        return generateView(viewId);}}

业务层使用方式如下:

adapter = new AbsUnityBaseRecyclerAdapter<CorePageEntity>() {    @Overridepublic void convert(CorePageEntity itemEntity, UnityRecyclerAdapterViewHolder viewHolder, int position) {      viewHolder.generateView(R.id.tvItemCommon, TextView.class).setText(itemEntity.getCorePageTitle());}

    @Overridepublic int getItemLayoutId(int viewType) {        return R.layout.simple_item_horizontal;}};

对于数据修改等操作,

adapter.getDataModifyHelper().setDataResource(        CorePageEntity.create(TestActivity.class),CorePageEntity.create(PullToRefreshActivity.class));

来自为知笔记(Wiz)

时间: 2024-10-13 01:07:17

Android适配器之基于BaseAdapter定义AbslistView万能适配器的相关文章

Android适配器之DataModifyHelper数据操作类的封装

编写适配器代码时常常被以下几个问题所困扰: 1.业务层和适配器中对同一组数据进行维护,难以管理 2.在业务层针对数据进行修改后必须通知适配器更新,否则提示The content of the adapter has changed but ListView did not receive anotification 3.业务层修改数据时充斥大量的非空&数据标准化等冗余代码 针对前两个问题,可以将数据交由适配器去管理,业务层对数据的增删改查均通过适配器进行处理,这样仅需要维护好adapter中的数

Android适配器之定义PagerAdapter万能适配器

一般使用pageAdapter需要实现getcount.isViewFromObject.instantiateItem.destroyItem等默认函数,其实完全可以抽取共有代码到父类当中. /** * Created by Xiaoxuan948 on 2015/10/27. * Desc: * 提示:先给adapter设置数据,再绑定适配器 setAdapter会调用instantiateItem方法 */public class AbsUnityBasePageAdapter<T> e

[转]Android适配器之ArrayAdapter、SimpleAdapter和BaseAdapter的简单用法与有用代码片段

收藏ArrayAdapter.SimpleAdapter和BaseAdapter的一些简短代码片段,希望用时方便想起其用法. 1.ArrayAdapter 只可以简单的显示一行文本 代码片段: [java] view plaincopy ArrayAdapter<String> adapter = new ArrayAdapter<String>( this, R.layout.item,//只能有一个定义了id的TextView data);//data既可以是数组,也可以是Li

Android适配器之ArrayAdapter、SimpleAdapter和BaseAdapter的简单用法与有用代码片段(转)

摘自:http://blog.csdn.net/shakespeare001/article/details/7926783 收藏ArrayAdapter.SimpleAdapter和BaseAdapter的一些简短代码片段,希望用时方便想起其用法. 1.ArrayAdapter 只可以简单的显示一行文本 代码片段: [java] view plaincopy ArrayAdapter<String> adapter = new ArrayAdapter<String>( this

BaseAdapter封装 实现万能适配器

1.封装ViewHodler 1 package com.example.utils; 2 3 import android.content.Context; 4 import android.graphics.Bitmap; 5 import android.util.SparseArray; 6 import android.view.LayoutInflater; 7 import android.view.View; 8 import android.view.ViewGroup; 9

Android应用项目中BaseAdapter、SimpleAdapter和ArrayAdapter中的三种适配器

一.写在前面: 本次我们来讲解一下Android应用中三个适配器:BaseAdapter.SimpleAdapter和ArrayAdapter.其中常见的是BaseAdapter,也是个人推荐使用的适配器. 二.深入了解: 1.什么是适配器? 适配器:在安卓中,顾名思义就是把数据变成符合界面风格的形式,并且通过ListView显示出来.也就是说适配器是数据和界面之间的桥梁. 适配器在数据库中的数据(后台)和显示页面(前端)中充当一个转换器的角色,数据库中的数据(如数组,链表,数据库,集合等)通过

RecyclerView的万能适配器+定义可以到底部自动刷新的RecyclerView

RecyclerView的重要性就不做重复说明了,为了方便以后直接使用写了这个,主要有: 万能适配器在使用的时候分为定义布局和绑定数据,方便直接套用.加入了底部刷新,需要配合自己写的RecyclerView一起使用,对于布局中各个子布局和控件可以做到响应各种点击事件: 首先抽取ViewHolder:这里的要点是用到了SparseArray(源码中类似ArrayList.直接使用Object数组进行实现): package com.fightzhao.baseadapterdemo.base; i

Android适配方案小结(三)

在Android适配方案小结(一).(二)中,我们了解了一些基本概念. 那么在具体开发中,我们应该注意什么呢. 首先,我们必须要知道,其实适配的关键在于两点: (1)不同分辨率设备的适配,这点在单位的使用上用dp.sp以及图片资源存放于不同的drawable文件夹就可以解决问题: (2)不同尺寸的适配,这点主要靠将相关值以及布局文件放置于不同的文件夹中来解决. 2.1 values文件夹 可以在工程下创建不同的values文件夹:values-sw480dp, values-sw600dp, v

Android进阶笔记10:Android 万能适配器

1. Android 万能适配器      项目中Listview GridView几乎是必用的组件,Android也提供一套机制,为这些控件绑定数据,那就是Adapter.用起来虽然还不错,但每次都需要去继承一个BaseAdapter,然后实现里面的一大堆方法,而我们每次最关心的无非就是getView方法,其余的方法几乎都是相同代码.这里是不是就可以优化起来呢?在其次,我们在使用Adapter的时候,为了优化性能,常常会创建一个Holder.而Holder里面每次存放的都是View,对Hole