

真香警告:即使不用饿了么订餐,也请务必收藏好该库
source link: https://www.tuicool.com/articles/mEFfE3Q
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

真香警告:即使不用饿了么订餐,也请务必收藏好该库!
Click here for reading English guide
由来
Linkage-RecyclerView 是一款基于 MVP 架构开发的二级联动列表控件。它是因 “RxJava 魔法师” 这个项目的需求而存在。
在最初寻遍了 GitHub 也没有找到合适的开源库(高度解耦、可远程依赖)之后,我决心研究参考现有开源项目关于二级联动的逻辑,并自己动手编写一个 高度解耦、轻松配置、可通过 Maven 仓库远程依赖 的真正的第三方库。
Linkage-RecyclerView 的个性化配置十分简单,依托于 MVP 的 “配置解耦” 特性,使用者无需知道内部的实现细节,仅通过实现 Config 类即可完成功能的定制和扩展。
此外,在不设置自定义配置的情况下,Linkage-RecyclerView 最少只需 一行代码即可运行起来 。
RxMagic 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:1.5.7'
2.依据默认的分组实体类 DefaultGroupedItem
的结构准备一串数据(以下以 JSON 为例)。
// DefaultGroupedItem.ItemInfo 包含三个字段: String title //(必填)二级选项的标题 String group //(必填)二级选项所在分组的名称,要和对应的一级选项的标题相同 String content //(选填)二级选项的内容
[ { "header": "优惠", "isHeader": true }, { "isHeader": false, "info": { "content": "好吃的食物,增肥神器,有求必应", "group": "优惠", "title": "全家桶" } }, { "header": "热卖", "isHeader": true }, { "isHeader": false, "info": { "content": "爆款热卖,月销超过 999 件", "group": "热卖", "title": "烤全翅" } } ]
3.在布局中引入 LinkageRecyclerView 。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.kunminx.linkage.LinkageRecyclerView android:id="@+id/linkage" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
4.在得到数据后,最少只需一行代码即可完成初始化。
List<DefaultGroupedItem> items = gson.fromJson(...); //一行代码完成初始化 linkage.init(items);
注意:如使用 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<ElemeGroupedItem.ItemInfo> { 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<ElemeLinkageItem>
,以及 new ILevelSecondaryAdapterConfig<ElemeLinkageItem.ItemInfo>()
这两处。
private void initLinkageDatas(LinkageRecyclerView linkage) { Gson gson = new Gson(); List<ElemeGroupedItem> items = gson.fromJson(...); linkage.init(items, new ILevelPrimaryAdapterConfig() { private Context mContext; public void setContext(Context context) { mContext = context; } @Override public int getLayoutId() { return R.layout.default_adapter_linkage_level_primary; } @Override public int getGroupTitleViewId() { return R.id.tv_group; } @Override public int getRootViewId() { return R.id.layout_group; } @Override public void onBindViewHolder( LinkageLevelPrimaryAdapter.LevelPrimaryViewHolder holder, String title, int position) { ((TextView) holder.mGroupTitle).setText(title); } @Override public void onItemSelected(boolean selected, TextView itemView) { itemView.setBackgroundColor(mContext.getResources().getColor(selected ? com.kunminx.linkage.R.color.colorLightBlue : com.kunminx.linkage.R.color.colorWhite)); itemView.setTextColor(ContextCompat.getColor(mContext, selected ? com.kunminx.linkage.R.color.colorWhite : com.kunminx.linkage.R.color.colorGray)); } }, new ILevelSecondaryAdapterConfig<ElemeGroupedItem.ItemInfo>() { private Context mContext; public void setContext(Context context) { mContext = context; } @Override public int getGridLayoutId() { return R.layout.adapter_eleme_secondary_grid; } @Override public int getLinearLayoutId() { return R.layout.adapter_eleme_secondary_linear; } @Override public int getHeaderLayoutId() { return R.layout.default_adapter_linkage_level_secondary_header; } @Override public int getHeaderTextViewId() { return R.id.secondary_header; } @Override public int getSpanCountOfGridMode() { return 2; } @Override public void onBindViewHolder( LevelSecondaryViewHolder holder, BaseGroupedItem<ElemeGroupedItem.ItemInfo> item, int position) { ((TextView) holder.getView(R.id.iv_goods_name)) .setText(item.info.getTitle()); Glide.with(mContext).load(item.info.getImgUrl()) .into((ImageView) holder.getView(R.id.iv_goods_img)); holder.getView(R.id.iv_goods_item).setOnClickListener(v -> { //TODO }); holder.getView(R.id.iv_goods_add).setOnClickListener(v -> { //TODO }); } @Override public void onBindHeaderViewHolder( LevelSecondaryHeaderViewHolder holder, BaseGroupedItem<ElemeGroupedItem.ItemInfo> item, int position) { //TODO } }); }
Thanks to
My Pages
Email: [email protected]
Home: KunMinX 的个人博客
Juejin: KunMinX 在掘金
KunMinX's WeChat Public Account(微信公众号):
License
Copyright 2018-2019 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.
Recommend
-
69
【编者按】作为加班拍档、创业伴侣、春运神器,曾几何时,方便面是我们生活中重要的“朋友”,然而这种景象却在近5年出现了戏剧性的逆转。统计显示,2011年之前,方便面销量在中国连续18年保持两位数增长,2013年的年销量更是创下462亿包的辉煌
-
33
高铁订餐 - 在线预订高铁外卖,沿途特色小吃送到座位 - NEXT
-
53
职场话题 - @freeer - 说下我的情况吧,16 年研究生毕业,工作也快 3 年了,1065,自由轻松不打卡,税后工资+公积金+福利+年终,一年到手 18 万左右。今年好几个同学都跳槽加薪,有点羡慕,也想去试试,但又舍不得这份
-
48
由来 LinkageRecyclerView 是一款基于 MVP 架构开发的二级联动列表控件。它是因 “RxJava 魔法师” 这个项目的需求而存在。 在最初寻遍了 GitHub 也没有找到合适的开源库(高度解耦、可远程依赖)之后,我决心研究参考现有开源项目关
-
71
前言 很高兴见到你! 上一期我在掘金发表了《重学安卓:Activity 的快乐你不懂!》,原本只是想给大家一把进阶的钥匙,能够因为文章从 0 到 1 的介绍,而对显示系统大家族 建立起感性的认识、并且埋下好奇的种子 去推动自己继续探究,没想到公众号后台 有不少
-
43
是软件工程安全的 Jetpack 音乐播放开源库!很高兴见到你! Jetpack-MusicPlayer 是一款基于 Jetpack MVVM 架构开发的 音乐播放控制组件,它是因 “Jetpack-MVVM-...
-
6
外卖订餐app开发的优势发布于 今天 07:21 随着社会经济水平的迅速发展,现代人的生活节奏越来越快,手机订餐已成为人们日常生活的一部分,办公室的白领一天三顿不离...
-
9
此 App 只在 iPhone 和 iPad 的 App Store 中提供。
-
6
V2EX › Visual Studio Code 也请为我 upvote!如果你在使用 vscode 中也遇到这样的烦恼
-
22
V2EX › 剧集 分享一些个人喜欢的美/英/欧美剧,有同好的也请分享一些给我
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK