真香警告:即使不用饿了么订餐,也请务必收藏好该库!

由来

Linkage-RecyclerView 是一款基于 MVP 架构开发的二级联动列表控件。它是因 “RxJava 魔法师” 这个项目的需求而存在。

在最初寻遍了 GitHub 也没有找到合适的开源库(高度解耦、可远程依赖)之后,我决心研究参考现有开源项目关于二级联动的逻辑,并自己动手编写一个 高度解耦、轻松配置、可通过 Maven 仓库远程依赖 的真正的第三方库。

Linkage-RecyclerView 的个性化配置十分简单,依托于 MVP 的 “配置解耦” 特性,使用者无需知道内部的实现细节,仅通过实现 Config 类即可完成功能的定制和扩展。

此外,在不设置自定义配置的情况下,Linkage-RecyclerView 最少只需 一行代码即可运行起来。

RxJava Magician

Eleme Linear

Eleme Grid

目标

Linkage-RecyclerView 的目标是:一行代码即可接入二级联动列表。

除了一键接入而省去 99% 不必要的、复杂的、重复的工作外,你还可以从这个开源项目获得的内容包括:

整洁的代码风格和标准的资源命名规范。

MVP 架构在编写第三方库中的最佳实践:使用者无需了解内部逻辑,通过实现接口即可轻松完成个性化配置。

优秀的代码分层和封装思想,在不做任何个性化配置的情况下,一行代码即可接入。

主体工程基于前沿的、遵循关注点分离的 Jetpack MVVM 架构。

AndroidX 和 Material Design 2 的全面使用。

ConstraintLayout 约束布局的最佳实践。

绝不使用 Dagger,绝不使用奇技淫巧、编写艰深晦涩的代码。

如果你正在思考 如何为项目挑选合适的架构 的话,这个项目值得你参考!

简单使用:

1.在 build.gradle 中添加对该库的依赖。

implementation 'com.kunminx.linkage:linkage-recyclerview:2.4.0'

提示:鉴于 Jcenter 的关闭,我们已将仓库迁移至 Maven Central,请自行在根目录 build.gradle 添加 mavenCentral()。

2.依据默认的分组实体类 DefaultGroupedItem 的结构准备一串数据。

// DefaultGroupedItem.ItemInfo 包含三个字段:

String title //(必填)二级选项的标题

String group //(必填)二级选项所在分组的名称,要和对应的一级选项的标题相同

String content //(选填)二级选项的内容

List list = new ArrayList<>();

//添加第 0 条记录:header 0

list.add(new TestGroupedItem("优惠", true));

//添加第 1 条记录:info 1

TestGroupedItem.ItemInfo info1 = new TestGroupedItem.ItemInfo();

info1.setContent("好吃的食物,增肥神器,有求必应");

info1.setGroup("优惠");

info1.setTitle("全家桶");

list.add(new TestGroupedItem(info1, false));

//添加第 2 条记录:header 2

list.add(new TestGroupedItem("优惠", true));

//添加第 3 条记录:info 3

TestGroupedItem.ItemInfo info3 =

new TestGroupedItem.ItemInfo("爆款热卖,月销超过 999 件", "热卖", "烤全翅");

list.add(new TestGroupedItem(info3, false));

3.在布局中引入 LinkageRecyclerView 。

xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/linkage"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

4.在得到数据后,最少只需一行代码即可完成初始化。

linkage.init(items);

温馨提示:

1.在实际的项目开发中,我们的做法通常是,从后端拿到和解析 JSON 数据,并对得到的数据进行遍历。在遍历过程中,我们实例化并装载本库的实体类对象到列表中,从而获得本库所能使用的列表数据。

2.注意:如使用 JSON,请在 ProGuard Rules 中为该实体类配置混淆白名单:

-keep class com.kunminx.linkage.bean.** {*;}

该库为一级和二级 Adapter 分别准备了 Config 接口(ILevelPrimaryAdapterConfig 和 ILevelSecondaryAdapterConfig),自定义配置时,即是去实现这两个接口,来取代默认的配置。

之所以设置成接口的形式,而非 Builder 的形式,是因为二级联动列表内部的联动逻辑需要指明关键的控件。接口相比 Builder 具有强制性,能够让使用者一目了然必须配置的内容,故而采用接口,通过 MVP 架构的方式来编写该库。

关于个性化配置,具体可以参考我在 ElemeGroupedItem 和 SwitchSampleFragment 中编写的案例:

Step1:根据需求扩展实体类

你需要根据需求,在 BaseGroupedItem 的基础上扩展分组实体类,具体的办法是,编写一个实体类,该实体类须继承于 BaseGroupedItem;该实体类的内部类 ItemInfo 也须继承于 BaseGroupedItem.ItemInfo。

以 Eleme 分组实体类为例,扩充 content、imgUrl、cost 三个字段:

public class ElemeGroupedItem extends BaseGroupedItem {

public ElemeGroupedItem(boolean isHeader, String header) {

super(isHeader, header);

}

public ElemeGroupedItem(ItemInfo item) { super(item); }

public static class ItemInfo extends BaseGroupedItem.ItemInfo {

private String content;

private String imgUrl;

private String cost;

public ItemInfo(String title, String group, String content) {

super(title, group);

this.content = content;

}

public ItemInfo(String title, String group, String content, String imgUrl) {

this(title, group, content);

this.imgUrl = imgUrl;

}

public ItemInfo(String title, String group, String content, String imgUrl, String cost) {

this(title, group, content, imgUrl);

this.cost = cost;

}

public String getContent() { return content; }

public void setContent(String content) { this.content = content; }

public String getImgUrl() { return imgUrl; }

public void setImgUrl(String imgUrl) { this.imgUrl = imgUrl; }

public String getCost() { return cost; }

public void setCost(String cost) { this.cost = cost; }

}

}

注意:如使用 JSON,请在 ProGuard Rules 中为该实体类配置混淆白名单。

Step2:实现接口,完成自定义配置

在装载数据和实现自定义配置时,泛型框中须指明你编写的实体类,注意 List,以及 new ILevelSecondaryAdapterConfig() 这两处。

private void initLinkageDatas(LinkageRecyclerView linkage) {

List items = gson.fromJson(...);

linkage.init(items, new ElemePrimaryAdapterConfig(), new ElemeSecondaryAdapterConfig());

}

private class ElemePrimaryAdapterConfig implements ILinkagePrimaryAdapterConfig {

private Context mContext;

public void setContext(Context context) { mContext = context; }

@Override

public int getLayoutId() { return R.layout.adapter_linkage_primary; }

@Override

public int getGroupTitleViewId() { return R.id.tv_group; }

@Override

public int getRootViewId() { return R.id.layout_group; }

@Override

public void onBindViewHolder(LinkagePrimaryViewHolder holder, boolean selected, String title) {

TextView tvTitle = (TextView) holder.mGroupTitle;

tvTitle.setText(title);

tvTitle.setBackgroundColor(mContext.getResources().getColor(

selected ? R.color.colorPurple : R.color.colorWhite));

tvTitle.setTextColor(ContextCompat.getColor(mContext,

selected ? R.color.colorWhite : R.color.colorGray));

}

}

private class ElemeSecondaryAdapterConfig implements

ILinkageSecondaryAdapterConfig {

private Context mContext;

public void setContext(Context context) { mContext = context; }

@Override

public int getGridLayoutId() { return 0; }

@Override

public int getLinearLayoutId() { return R.layout.adapter_eleme_secondary_linear; }

@Override

public int getHeaderLayoutId() { return R.layout.adapter_linkage_secondary_header; }

@Override

public int getFooterLayoutId() { return 0; }

@Override

public int getHeaderTextViewId() { return R.id.secondary_header; }

@Override

public int getSpanCountOfGridMode() { return SPAN_COUNT_FOR_GRID_MODE; }

@Override

public void onBindViewHolder(LinkageSecondaryViewHolder holder,

BaseGroupedItem item) {

((TextView) holder.getView(R.id.iv_goods_name)).setText(item.info.getTitle());

holder.getView(R.id.iv_goods_item).setOnClickListener(v -> {

//TODO

});

}

@Override

public void onBindHeaderViewHolder(LinkageSecondaryHeaderViewHolder holder,

BaseGroupedItem item) {

((TextView) holder.getView(R.id.secondary_header)).setText(item.header);

}

@Override

public void onBindFooterViewHolder(LinkageSecondaryFooterViewHolder holder,

BaseGroupedItem item) {

//TODO

}

}

Thanks to

My Pages

License

Copyright 2018-present KunMinX

Licensed under the Apache License, Version 2.0 (the "License");

you may not use this file except in compliance with the License.

You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software

distributed under the License is distributed on an "AS IS" BASIS,

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and

limitations under the License.

don't android xml,GitHub - KunMinX/Linkage-RecyclerView: 即使不用饿了么订餐,也请务必收藏好该库! 一行代码即可接入,二级联动订餐列表。...相关推荐

  1. 牛气!GitHub 标星 119K+!这些神器仅需一行代码即可下载全网视频!

    作者 | JackTian 来源 | 杰哥的IT之旅(ID:Jake_Internet) 今天这篇文章的内容对于经常浏览各大视频网站的同学来说,是一大神器工具.当你看到自己目前所需的视频时想尽各种办法 ...

  2. GitHub 标星 119K+!这些神器仅需一行代码即可下载全网视频!

    作者 | JackTian 来源 | 杰哥的IT之旅(ID:Jake_Internet) 头图 |  CSDN 下载自东方IC 大家好,我是 JackTian. 今天这篇文章的内容对于经常浏览各大视频 ...

  3. GitHub 标星 120K+!这些神器仅需一行代码即可下载全网视频!

    大家好,我是 JackTian. 今天这篇文章的内容对于经常浏览各大视频网站的同学来说,是一大神器工具.当你看到自己目前所需的视频时想尽各种办法保存至本地,方便后期再次回看.恰巧有些视频可能需要会员才 ...

  4. 【效率】GitHub 标星 119K+!这些神器仅需一行代码即可下载全网视频!

    作者 | JackTian 来源 | 杰哥的IT之旅(ID:Jake_Internet) 转载请联系授权(微信ID:Hc220066) 大家好,我是 JackTian. 今天这篇文章的内容对于经常浏览 ...

  5. android xml talkback,如何为RecyclerView中的项目自定义TalkBack使用提示?

    我想让我的应用程序可用于盲人 . 在RecyclerView中点击子项时,它会突出显示,而在双击时,它会打开子项的类别 . Basically one has to double tap to per ...

  6. android 二级联动列表,Linkage-RecyclerView

    软件简介 Linkage-RecyclerView 是一款基于 MVP 架构开发的二级联动列表控件.它是因 "RxJava 魔法师" 这个项目的需求而存在. 在最初寻遍了 GitH ...

  7. Android 快速实现新手引导层的库,通过简洁链式调用,一行代码实现引导层的显示

    NewbieGuide 项目地址:huburt-Hu/NewbieGuide  简介:Android 快速实现新手引导层的库,通过简洁链式调用,一行代码实现引导层的显示 更多:作者   提 Bug 标 ...

  8. Android Hook基础-一行代码实现开屏广告

    需求背景 多个产品线都需要实现开屏广告,我们产品广告都是接的我们自家广告SDK,而SplashActivity只是几行代码请求我们广告,广告SDK会把View封装好返回来,SplashActivity ...

  9. android一行代码实现在线更新

    App在线更新插件 整合了一下网上的有关app的在线更新的东西,懒得打成jar包了,照着步骤做可以实现app在线更新,主界面添加一行代码即可,详细步骤见说明.不依赖第三方更新服务,需要自己搭建后台服务 ...

最新文章

  1. PHP实现将任意尺寸的图片裁剪后等比缩放到任意尺寸的透明图片上,并实现图片翻转...
  2. CTF web题总结--绕过正则表达式
  3. UOJ #584. 天天去哪吃
  4. 简单的创建一个性能计数器
  5. Shiro——从零开始进行详解官方入门案例
  6. 表格是html文档的基本属性吗,Html
  7. wps嵌入字体后也不改变_冬至后的君子兰,养护方式要改变,不然过年不开花
  8. 用python写出九九乘法表
  9. LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset
  10. Android AbsoluteLayout 绝对布局
  11. Eclipse没有Web插件和JavaEE插件咋整
  12. 二手青春——代码之路1
  13. node.js如何制作命令行工具(一)
  14. linux 修改文件的权限
  15. 企业邮箱客户端服务器异常,企业邮箱使用客户端连接提示“不知道这样的主机”的解决...
  16. 使用GoldWave制作“淡入/淡出”效果
  17. python图片截取斜四边形_opencv 截取任意四边形区域的图像
  18. (2019春)软件构造:雨课堂试卷(第3章)
  19. php 什么是占位符,php中的占位符
  20. 分享一些C++软件开发后台开发复习必备电子书单

热门文章

  1. FFmpeg将H264和AAC合成为MP4
  2. 入門篇-耦合Coupling AC/DC/GND差別在哪
  3. 手把手教你goland远程调试
  4. 使用catlog管理rman
  5. 网页怎么做成二维码?如何扫码查看网页链接?
  6. mkdocs-with-pdf 0.9.3的安装使用
  7. GAZEBO构建室外环境地图之创建高度图
  8. 脑洞大爆炸:5款创客DIY套件,强烈推荐!
  9. 数值分析——Gauss-Legendre 求积分(Matlab实现)
  10. tws耳机哪个品牌好?双十二tws蓝牙耳机推荐