Flutter高内聚组件怎么做?阿里闲鱼打造开源高效方案!
fish_redux是闲鱼技术团队打造的flutter应用开发框架,旨在解决页面内组件间的高内聚、低耦合问题。开源地址:https://github.com/alibaba/fish-redux
从react_redux说起
redux对于前端的同学来说是一个比较熟悉的框架了,fish_redux借鉴了redux单项数据流思
想。在flutter上说到redux,大家可能第一反应会类比到react上的react_redux。在react_redux中有个重要的概念——connect,
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
简单得说,connect允许使用者从Redux store中获取数据并绑定到组件的props上,可以dispatch一个action去修改数据。
那么fish_redux中的connector是做什么的呢?为什么说connector解决了组件内聚的问题?我们应该如何理解它的设计呢?
connector in fish_redux
尽管都起到了连接的作用,但fish_redux与react_redux在抽象层面有很大的不同。
fish_redux本身是一个flutter上的应用框架,建立了自己的component体系,用来解决组件内的高内聚和组件间的低耦合。从connector角度来说,如何解决内聚问题,是设计中的重要考量。
fish_redux自己制造了Component
树,Component
聚合了state和dispatch,每一个子Component
的state通过connector
从父Component
的state中筛选。如图所示:
可以看到,fish_redux的connector的主要作用把父子Component
关联起来,最重要的操作是filter。state从上之下是一个严谨的树形结构,它的结构复用了Component
的树形结构。类似一个漏斗形的数据管道,管理数据的分拆与组装。它表达了如何组装一个Component
。
而对于react_redux来说,它主要的作用在于把react框架和redux绑定起来,重点在于如何让React component具有Redux的功能。
从图中可以看到,react_redux和React是平行的结构,经过mapStateToProps
后的state也不存在严谨的树形结构,即对于一个React component来说,它的state来自于Redux store而不是父component的state。从框架设计的角度来说,react_redux最重要的一个操作就是attach。
源码分析
说完概念,我们从源码的角度来看看fish_redux中的connector是如何运作的,以fish_redux提供的example为例。
class ToDoListPage extends Page<PageState, Map<String, dynamic>> {ToDoListPage(): super(...dependencies: Dependencies<PageState>(adapter: ToDoListAdapter(),slots: <String, Dependent<PageState>>{'report': ReportConnector() + ReportComponent()}),...);
}
在ToDoListPage
的构造函数中,向父类构造传递了一个Dependencies
对象,在构造Dependencies
时,参数
slots
中包含了名叫"report"的item,注意这个item的生成,是由一个
ReportConnector
+ReportComponent
产生的。
从这里我们得出一个简单却非常重要的结论:
在fish_redux中,一个Dependent = connector + Component 。
Dependent
代表页面拼装中的一个单元,它可以是一个Component
(通过buildComponent函数产
生),也可以是一个Adapter
(由buildAdapter函数产生)。这样设计的好处是,对于View拼装操作
来说,Dependent
对外统一了API而不需要透出更多的细节。
根据上面我们得出的结论,connector
用来把一个更小的Component
单元链接到一个更大的
Component
或Adapter
上。这与我们之前的描述相符合。
connector到底是什么
知道了connector
的基本作用,我们来看一下它到底链接了哪些东西以及如何链接。
先来看一下ReportConnector
类的定义:
class ReportConnector extends ConnOp<PageState, ReportState>
ReportConnector
继承了ConnOp
类,所有connector
的操作包括+操作,都来自于ConnOp
类。
set/get
既然是数据管道,就会有获取和放置
set
函数的入参很好得表达了T
和P
的意思,即把一个P
类型的subState
合并到T
类型的
state
中。
再回头看get
函数,就很好理解了,get
函数表达的就是如何从T
类型的state
中获取P
类型
的subState
供Dependent
使用。
operator +
+
操作符的重载是我们最初看到connector作用的地方,也是connector发挥作用的入口。
Logic
是Component
和Adapter
的父类,它表示页面组装元素的逻辑层,里面包含了
reducer
/effect
/higherEffect
等与逻辑相关的元素以及它的组装过程。
operator+
调用了createDependent
函数,接着会调用到_Dependent
类的构造函数,这里将
logic
和connector
放入_Dependent
内部,在后面fish_redux对Component
组装的过程中,connector会随着外部对_Dependent
中函数的调用发挥作用。
connector正式登场
铺垫了这么多,是该connector正式发挥作用的时候了。
get
我们以Component
为例,会调用到_Dependent
的buildComponent
函数:
Widget buildComponent(MixedStore<Object> store, Get<T> getter) {final AbstractComponent<P> component = logic;return component.buildComponent(store, () => connector.get(getter()));
}
这里的logic
实际就是一个Component
对象,在调用Component
的buildComponent
函数的
时候,使用get
函数从一个大的父state中获取到当前Component
需要的数据集。接下去,这个变换后的子state将被用在例如ViewBuilder
或Redcuer
函数中。
这是connector在数据获取上的作用。
set
还是在_Dependent
类里面,看createSubReducer
函数:
SubReducer<T> createSubReducer() {final Reducer<P> reducer = logic.reducer;return reducer != null ? connector.subReducer(reducer) : null;
}
首现从一个Logic
(这里实际上是一个Component
)对象中获取到外部设置进来的reducer
,接着
调用subReducer
返回一个SubReducer
对象。SubReducer
是一个被wrap后的Reducer
subReducer
的实现在MutableConn
中,ConnOp
继承了MutableConn
类,也获得了这个能
力。
SubReducer<T> subReducer(Reducer<P> reducer) {return (T state, Action action, bool isStateCopied) {final P props = get(state);if (props == null) {return state;}final P newProps = reducer(props, action);final bool hasChanged = newProps != props;final T copy = (hasChanged && !isStateCopied) ? _clone<T>(state) : state;if (hasChanged) {set(copy, newProps);}return copy;};
}
它首现通过get
函数得到一个变换后的数据集props
,接着调用原始的reducer
函数进行逻辑处
理,这里有一个优化也是SubReducer
的作用,如果数据集在经过reducer
处理之后发生了变化,
并且state已经被copy过一次了(isStateCopied==true),就直接把newProps
通过set
函数
更新到state中去。(这个优化可以防止多个子state发生变化的时候父state被拷贝多次)
至此,connector在数据更新上的作用也体现出来了。
ReportConnector
最后,就好理解ReportConnector的实现了:
class ReportConnector extends ConnOp<PageState, ReportState> {@overrideReportState get(PageState state) {final ReportState reportState = ReportState();reportState.total = state.toDos.length;reportState.done =state.toDos.where((ToDoState tds) => tds.isDone).toList().length;return reportState;}@overridevoid set(PageState state, ReportState subState) {}
}
很明显的,在get
函数中,ReportState
从PageState
中获得了total/done字段。
总结
闲鱼客户端的详情页完全使用了fish_redux进行了重构,通过高内聚的Component+connector
形式,使得Component
可以被大量复用,很好得支持了5中类型的详情页。未来我们会基于fish_redux强大的扩展能力制作更多组件来满足不同业务对于框架的需求。
原文链接
本文为云栖社区原创内容,未经允许不得转载。
Flutter高内聚组件怎么做?阿里闲鱼打造开源高效方案!相关推荐
- 走近科学,探究阿里闲鱼团队通过数据提升Flutter体验的真相
背景 闲鱼客户端的flutter页面已经服务上亿级用户,这个时候Flutter页面的用户体验尤其重要,完善Flutter性能稳定性监控体系,可以及早发现线上性能问题,也可以作为用户体验提升的衡量标准. ...
- 看!闲鱼又开源了一个 Flutter 开发利器
阿里妹导读:随着 Flutter 这一框架的快速发展,有越来越多的业务开始使用 Flutter 来重构或新建其产品.但在我们的实践过程中发现,一方面 Flutter 开发效率高,性能优异,跨平台表现好 ...
- 《Flutter in action》开放下载!闲鱼Flutter企业级实践精选
复制链接到浏览器 https://yq.aliyun.com/download/3792?utm_content=g_1000081730 下载. 闲鱼是国内最早使用Flutter的团队,也是Flut ...
- 闲鱼副业怎么做?闲鱼怎么搞副业?闲鱼能干啥副业?
闲鱼,这个词的热度一直居高不下,虽然大家对它的评价褒贬不一,但确实是最适合0基础小白 ,开启网赚之路的不二之选.现在我将操作方法交给大家. 一.养号 顾名思义就是将闲鱼新账号进行一些模拟正常用户的操作 ...
- 阿里闲鱼App服务端在ServiceMesh的探索和实践
文章来源:咸鱼技术(XYtech_Alibaba) 作者:柬超 背景 在阿里服务端开发以Java为主的大背景下,其他异构语言业务如何调用现有Java服务,如何与集团中间件打通,就成为使用非Java语言 ...
- 找懂的大佬做一个闲鱼监控软件,大概要求如下。
闲鱼采集及监控下单软件开发 1,点击宝贝右键打开网页 2,点击宝贝右键拉黑卖家 3,点击宝贝右键清空列表 4,强制聊天,软件界面显示的宝贝如果已经被别人付款,可以实现在软件跟卖家沟通,软件界面有与卖家 ...
- 向消息延迟说bybye:闲鱼消息及时到达方案(详细)
背景 IM消息作为闲鱼用户重要的交易咨询工具,核心目标有两点,第一是保证用户的消息不丢失,第二是保证用户的消息及时送达接收方.IM消息根据消息的接收方设备是否在线,分为离线和在线推送,数据显示目前闲鱼 ...
- GVS视声挺进西藏,为阿里地区人民医院打造全时高效智慧医疗体验
项目介绍: 项目名称:阿里地区人民医院传染病院区 项目地址:西藏自治区阿里地区噶尔县北京南路10号 项目规模:占地面积3.7万平方米,项目建筑面积约5297.39平方米 应用系统: 门诊排队叫号系统 ...
- 阿里技术分享:闲鱼IM基于Flutter的移动端跨端改造实践
本文由阿里闲鱼技术团队祈晴分享,本次有修订和改动,感谢作者的技术分享. 1.内容概述 本文总结了阿里闲鱼技术团队使用Flutter在对闲鱼IM进行移动端跨端改造过程中的技术实践等,文中对比了传统Nat ...
最新文章
- javascript中replace使用方法总结
- 2021年跨境电商市场怎么样?新手商家入驻还有机会吗?
- Windows Error Report
- 软文推荐:常用 Java 静态代码分析工具的分析与比较
- 使用Zuul和Spring Boot创建API网关
- [html] 说说你对html的嵌套规范的理解,都有哪些规范呢?
- java中的private public protected
- js change事件 获取新值和旧值_前端总结(JS篇)
- 信息学奥赛一本通(1238:一元三次方程求解)
- matlab控制树莓派3b,树莓派3B+ 手机h5网页控制GPIO
- SpringMVC测试框架(转载)
- 【北大知识图谱】知识图谱的关键技术及其智能应用
- Python操作SQLAlchemy
- 2018-2019的裁员风波(程序员要有危机意识,程序员堪比娱乐圈,更新换代快)
- 在Linux Mint 19.2 XFCE(x64)中安装Canon LBP2900+打印机驱动程序
- MPI学习-点对点通信
- html如何添加时钟效果,HTML5实现时钟效果
- 什么是千行代码缺陷率?
- matlab的tfdata函数_MATLAB 主要函数指令表(按功能分类)
- 信息论 | 计算离散信源的信息量和熵的MATLAB实现(函数封装调用)
热门文章
- 理发店管理系统java_美容美发店管理系统的设计与实现(JSP,SQLServer)(含录像)
- 【LeetCode笔记】283. 移动零(Java)
- java代码中 作用_Java利用开发中代码生成工具的作用
- effective python目录_Effective python(七):协作开发
- 加载中图片 转圈_对话洛可可平面设计师:平面设计中的效率瓶颈
- statuml怎么添加用户_UML课后习题答案
- python打包的exe如何免杀_如何使用Python进行Payload免杀
- bcp out 带列名导出_从零开始学习 MySQL 系列索引、视图、导入和导出
- 三甲医院his系统源码_三甲医院科研管理系统是什么,科研成果包括哪些
- 22岁大学生获谷歌天价offer,击败6000人年薪百万