Android 万能适配器BRVAH

作者: i小灰 | 来源:发表于2021-03-08 15:30 被阅读0次

    概述

    在Android开发过程中,我们经常会用到adapter。因为adapter在基本使用的过程中,代码比较繁琐,于是进行一个简单封装,使调用起来更加简单便捷。这节就来讲讲这个适配器的封装吧。

    前言

    在Android开发过程中,我们经常会用到adapter。因为adapter在基本使用的过程中,代码比较繁琐,于是进行一个简单封装,使调用起来更加简单便捷。这节就来讲讲这个适配器的封装吧。

    今天涉及的内容:

    1. adapter库依赖
    2. 封装类ComAdapter和GroupAdapter概述
    3. 通用适配器ComAdapter的使用
    4. 分组适配器GroupAdapter的使用
    5. MainActivity中调用示例
    6. 效果图和项目结构图

    先来波adapter使用的效果图吧


    image

    一. adapter库依赖

    Github地址
    本adapter的封装是建立在一个第三方库的基础之上的。在使用之前,你需要添加该库的依赖:
    将JitPack存储库添加到您的构建文件中(项目根目录下build.gradle文件):

    allprojects {
        repositories {
            google()
            jcenter()
            maven { url 'https://jitpack.io' }
        }
    }
    

    添加依赖项以最新版本为准:

    dependencies {
        implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.34'
    }
    

    二.封装类ComAdapter和GroupAdapter概述

    适配器库BaseRecyclerViewAdapterHelper是一个专注adapter的库,里面有一个适配器基类:BaseQuickAdapter,为了方便日常调度使用,我在BaseQuickAdapter基础上再度扩展,分别整合了两个adapter基类:ComAdapter和GroupAdapter。
    ComAdapter:基于一般的列表或九宫格布局的使用
    GroupAdapter:基于简单的分组列表展示使用。

    三.通用适配器ComAdapter的使用

    ComAdapter是一个通用适配器基类,里面集成了adapter创建需要的一些基本方法,包括控件初始化,获取布局对象,加载动画,列表数据加载,控件点击事件监听等方法。 当你要实现一个线性列表,需要创建adapter的时候,继承ComAdapter可以帮你快速实现自己的adapter。

    3.1 继承ComAdapter,写自己的Adapter

    当RecyclerView加载列表的时候,需要一个适配器(NameAdapter),你可以像这样快速来创建它:

    public class NameAdapter<T>extends ComAdapter {
        private TextView mTvName;
        public NameAdapter(List<T> data, Context context) {
            //加载布局和数据
            super(R.layout.item_layout, data, context);
        }
        @Override
        public <T>void initView(BaseViewHolder viewHolder, T obj) {
            //控件初始化
            mTvName=viewHolder.getView(R.id.tv);
        }
        @Override
        public <T>void initData(BaseViewHolder viewHolder, T obj) {
            String name=obj.toString();
            mTvName.setText(name);
        }
        @Override
        public <T>void setListener(BaseViewHolder viewHolder, T obj) {
            //添加控件监听
            addOnClickListener(mTvName,viewHolder,obj);
        }
    }
    
    3.2 线性布局调用
    mNames=new ArrayList<>();
    //for (int i = 0; i < 10; i++) {
    //    mNames.add("小黄"+i);
    //}
    mNameAdapter=new NameAdapter<>(mNames,MainActivity.this);
    mNameAdapter.setRecyclerLinearManager(mRecyclerView);
    
    3.3 九宫格布局调用
    mNames=new ArrayList<>();
    //for (int i = 0; i < 10; i++) {
    //    mNames.add("小黄"+i);
    //}
    mNameAdapter=new NameAdapter<>(mNames,MainActivity.this);
    mNameAdapter.setRecyclerGridManager(mRecyclerView,4);
    
    3.4 设置分割线,返回RecyclerView.ItemDecoration对象
    
    //设置线性布局分割线
    LinearDividerItemDecoration linearDivider=mNameAdapter.setLinearLayoutItemSpace(mRecyclerView,5,R.color.colorAccent);
    //设置九宫格局分割线
    GridDividerItemDecoration gridDivider=mNameAdapter.setGridLayoutItemSpace(mRecyclerView,5,R.color.colorAccent);
    
    
    3.5 移除分割线
    /**移除RecycleView间距**/
    removeItemSpace(RecyclerView recyclerView,  RecyclerView.ItemDecoration divider)
    
    3.6 点击事件
           //点击事件
           mNameAdapter.setOnItemClickListener(new AdapterHelper.OnItemClickListener() {
                @Override
                public void itemClickListener(View view, BaseViewHolder viewHolder, Object obj) {
                    switch (view.getId()) {
                        case R.id.tv:
                            ToastUtil.shortShow("====1====="+obj.toString());
                            break;
                        default:
                            break;
                    }
                }
            });
    

    四. 分组适配器GroupAdapter的使用

    GroupAdapter是一个列表分组显示的适配器基类,里面集成了adapter创建需要的一些基本方法,包括控件初始化,获取布局对象,加载动画,列表数据加载,控件点击事件监听等方法。 当你要船创建一个分组显示功能的adapter,继承GroupAdapter可方便快捷实现

    4.1 javaBean继承SectionEntity类

    GroupAdapter显示的数据,都需要用javaBean进行封装。并且JavaBean需要继承SectionEntity类,然后重写含(boolean isHeader, String header)参数的构造方法。 以Person对象为例,你需要这样处理:

    public class Person extends SectionEntity {
        private String name;
        private int age;
        public Person(boolean isHeader, String header) {
            super(isHeader,header);
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    4.2 继承GroupAdapter,写自己的adapter

    然后写一个自己的adapter,继承自GroupAdapter,以PersonAdapter为例:

    public class PersonAdapter<T> extends GroupAdapter {
        //header
        private TextView mTvHeader;
        //item
        private TextView mTvItem;
        public PersonAdapter(List<T> data, Context context) {
            super(R.layout.item_layout, R.layout.header_layout, data,context);
        }
        @Override
        protected void convertHead(BaseViewHolder viewHolder, SectionEntity item) {
            //标题相关所有都在此处理
            //标题初始化
            mTvHeader=viewHolder.getView(R.id.tv_title);
            //标题数据处理
            mTvHeader.setText(item.header);
            //标题点击事件
            addOnClickListener(mTvHeader,viewHolder,item);
        }
        @Override
        public <T>void initView(BaseViewHolder viewHolder, T obj) {
            //item初始化
            mTvItem=viewHolder.getView(R.id.tv);
        }
        @Override
        public <T>void initData(BaseViewHolder viewHolder, T obj) {
            //item数据处理
            Person person= (Person) obj;
            mTvItem.setText("姓名:"+person.getName()+"     年龄:"+person.getAge());
        }
        @Override
        public <T>void setListener(BaseViewHolder viewHolder, T obj) {
            //item中控件监听
            addOnClickListener(mTvItem,viewHolder,obj);
        }
    }
    

    其中PersonAdapter(List data, Context context)构造方法的super方法中,要引入两个布局id,一个是item的一个是header的。 Header相关方法都在convertHead中处理。item的相关处理在initView,initData和setListener方法中进行。

    4.3 线性布局使用
           mPersonList=new ArrayList<>();
           //for (int i = 0; i < 10; i++) {
           //Person person;
           //if(i%7==0){//header
           //   person=new Person(true,"标题"+i);
           //}else{//item
           //   person=new Person(false,null);
           //   person.setName("小黑"+i);
           //   person.setAge(25+i);
           // }
           //   mPersonList.add(person);
           //}
           mPersonAdapter=new PersonAdapter<>(mPersonList,MainActivity.this);
           mPersonAdapter.setRecyclerLinearManager(mRecyclerView);
    
    4.4 九宫格布局使用
            mPersonList=new ArrayList<>();
            //for (int i = 0; i < 10; i++) {
            //Person person;
            //if(i%7==0){//header
            //   person=new Person(true,"标题"+i);
            //}else{//item
            //   person=new Person(false,null);
            //   person.setName("小黑"+i);
            //   person.setAge(25+i);
            // }
            //   mPersonList.add(person);
            //}
            mPersonAdapter=new PersonAdapter<>(mPersonList,MainActivity.this);
            mPersonAdapter.setRecyclerGridManager(mRecyclerView,3);
    
    4.5 设置分割线,返回RecyclerView.ItemDecoration对象

    线性布局的时候,可以像下面这样设置分割线:

    //线性布局分割线
    LinearDividerItemDecoration linearDivider=mPersonAdapter.setLinearLayoutItemSpace(mRecyclerView, 5, R.color.colorAccent);
    

    注意: 在实现分组适配器<即继承GroupAdapter的adapter>不能使用setGridLayoutItemSpace给列表设置分割线,会出现ui上显示的bug,为了避免 用户使用不当,我已经将GroupAdapter类中的setGridLayoutItemSpace抛出异常并做以错误提示。大家若还是需要在分组九宫格布局中做分割线的话, 需要自己在布局中,或者在adapter中处理数据的时候,用代码来实现分割线效果。

    4.6 移除分割线
    /**移除RecycleView间距**/
    removeItemSpace(RecyclerView recyclerView, RecyclerView.ItemDecoration divider)
    
    4.7 点击事件

    若要设置adapter的点击事件,你可以像下面这样写:

            //点击事件
            mPersonAdapter.setOnItemClickListener(new AdapterHelper.OnItemClickListener() {
                @Override
                public void itemClickListener(View view, BaseViewHolder viewHolder, Object obj) {
                    Person person= (Person) obj;
                    switch (view.getId()) {
                        case R.id.tv_title://header
                            ToastUtil.shortShow("===="+person.header+"===");
                            break;
                        case R.id.tv://item
                            ToastUtil.shortShow("===="+person.getName()+"===");
                            break;
                        default:
                            break;
                    }
                }
            });
    

    五.MainActivity中调用示例

    下面贴出adapter在MainActivity中使用的代码:

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
        private Button mBtn1;
        private Button mBtn2;
        private Button mBtn3;
        private Button mBtn4;
        private RecyclerView mRecyclerView;
        private List<String>mNames;
        private NameAdapter<String>mNameAdapter;
        private List<Person>mPersonList;
        private PersonAdapter<Person>mPersonAdapter;
        private LinearDividerItemDecoration mLinearDivider;
        private GridDividerItemDecoration mGridDivider;
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initData();
            setListener();
        }
        private void initData() {
            mBtn1 = findViewById(R.id.btn1);
            mBtn2 = findViewById(R.id.btn2);
            mBtn3 = findViewById(R.id.btn3);
            mBtn4 = findViewById(R.id.btn4);
            mRecyclerView = findViewById(R.id.rv);
            mBtn1.setText("通用线性");
            mBtn2.setText("通用九宫");
            mBtn3.setText("分组线性");
            mBtn4.setText("分组九宫");
        }
        private void setListener() {
            mBtn1.setOnClickListener(this);
            mBtn2.setOnClickListener(this);
            mBtn3.setOnClickListener(this);
            mBtn4.setOnClickListener(this);
        }
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn1://通用布局线性测试
                    commonLinearLayout();
                    break;
                case R.id.btn2://通用布局九宫格测试
                    commonGridLayout();
                    break;
                case R.id.btn3://分组布局线性测试
                    diffGropLinearLayout();
                    break;
                case R.id.btn4://分组布局九宫格测试
                    diffGropGridLayout();
                    break;
                default:
                    break;
            }
            //点击事件
            commonDiffClick();
        }
        private void initCommonData(){
            //通用布局
            if(mNames==null) {
                mNames = new ArrayList<>();
            }
            mNames.clear();
            for (int i = 0; i < 10; i++) {
                mNames.add("小黄" + i);
            }
        }
        private void initdiffGropData(){
            //分组布局
            if(mPersonList==null) {
                mPersonList = new ArrayList<>();
            }
            mPersonList.clear();
            for (int i = 0; i < 10; i++) {
                Person person;
                if(i%7==0){//header
                    person=new Person(true,"标题"+i);
                }else{//item
                    person=new Person(false,null);
                    person.setName("小黑"+i);
                    person.setAge(25+i);
                }
                mPersonList.add(person);
            }
        }
        /**
         * 通用布局线性测试
         **/
        private void commonLinearLayout() {
            initCommonData();
            mNameAdapter = new NameAdapter<>(mNames, MainActivity.this);
            mNameAdapter.setRecyclerLinearManager(mRecyclerView);
            //清除旧的分割线
            mNameAdapter.removeItemSpace(mRecyclerView,mLinearDivider);
            mNameAdapter.removeItemSpace(mRecyclerView,mGridDivider);
            //设置分割线
            mLinearDivider=mNameAdapter.setLinearLayoutItemSpace(mRecyclerView, 5, R.color.colorAccent);
        }
        /**
         * 通用布局九宫格测试
         **/
        private void commonGridLayout() {
            initCommonData();
            mNameAdapter = new NameAdapter<>(mNames, MainActivity.this);
            mNameAdapter.setRecyclerGridManager(mRecyclerView, 3);
            //清除旧的分割线
            mNameAdapter.removeItemSpace(mRecyclerView,mLinearDivider);
            mNameAdapter.removeItemSpace(mRecyclerView,mGridDivider);
            //设置分割线
            mGridDivider=mNameAdapter.setGridLayoutItemSpace(mRecyclerView, 5, R.color.colorAccent);
        }
        /**
         * 分组布局线性测试
         **/
        private void diffGropLinearLayout() {
            initdiffGropData();
            mPersonAdapter=new PersonAdapter<>(mPersonList,MainActivity.this);
            mPersonAdapter.setRecyclerLinearManager(mRecyclerView);
            //清除旧的分割线
            mNameAdapter.removeItemSpace(mRecyclerView,mLinearDivider);
            mNameAdapter.removeItemSpace(mRecyclerView,mGridDivider);
            //设置分割线
            mLinearDivider=mPersonAdapter.setLinearLayoutItemSpace(mRecyclerView, 5, R.color.colorAccent);
        }
        /**
         * 分组布局九宫格测试
         **/
        private void diffGropGridLayout() {
            initdiffGropData();
            mPersonAdapter=new PersonAdapter<>(mPersonList,MainActivity.this);
            mPersonAdapter.setRecyclerGridManager(mRecyclerView,3);
            //清除旧的分割线
            mNameAdapter.removeItemSpace(mRecyclerView,mLinearDivider);
            mNameAdapter.removeItemSpace(mRecyclerView,mGridDivider);
        }
        /**点击事件**/
        private void commonDiffClick(){
            //通用布局点击事件
            if(mNameAdapter!=null) {
                mNameAdapter.setOnItemClickListener(new AdapterHelper.OnItemClickListener() {
                    @Override
                    public void itemClickListener(View view, BaseViewHolder viewHolder, Object obj) {
                        switch (view.getId()) {
                            case R.id.tv:
                                ToastUtil.shortShow("====1=====" + obj.toString());
                                break;
                            default:
                                break;
                        }
                    }
                });
            }
            //分组布局点击事件
            if(mPersonAdapter!=null) {
                mPersonAdapter.setOnItemClickListener(new AdapterHelper.OnItemClickListener() {
                    @Override
                    public void itemClickListener(View view, BaseViewHolder viewHolder, Object obj) {
                        Person person = (Person) obj;
                        switch (view.getId()) {
                            case R.id.tv_title://header
                                ToastUtil.shortShow("====" + person.header + "===");
                                break;
                            case R.id.tv://item
                                ToastUtil.shortShow("====" + person.getName() + "===");
                                break;
                            default:
                                break;
                        }
                    }
                });
            }
        }
    }
    

    六. 效果图和项目结构图

    效果图


    image

    项目结构图


    image

    最后

    虽然万能适配器方便好用,但是我还是推荐使用原生写法,因为原生写法更灵活,不会出现莫名的问题。万能适配器的动画目前可能有点毛病,谨慎使用列表动画!

    相关文章

      网友评论

        本文标题:Android 万能适配器BRVAH

        本文链接:https://www.haomeiwen.com/subject/udipqltx.html