SmartDialog迁移至4.0:一份真诚的迁移说明
前言
一个开源库,随着不断的迭代优化,难免会遇到一个很痛苦的问题
- 最初的设计并不是很合理:想添加的很多新功能都受此掣肘
想使得该库更加的强大和健壮,必须要做一个重构
- 因为重构涉及到对外暴露的api,所以大家会遇到一个比较烦躁的问题:更新版本后,会大面积报错
- 我考虑了很久,到底怎么帮大家快速迁移呢?最终想到了一个还算合理的方案
对于flutter_smart_dialog 4.0版本的改动,很多是为了解决自己以前考虑不周的历史遗留,以前这个库的初心,主要是为了解决loading和dialog穿透问题;现在扩展到:custom dialog,attach dialog,loading,toast,最初的设计真的力不从心了,config中的api难以去细分的控制这四个模块功能,一些参数的设计基于现在的功能和场景也不太合理等等
希望大家能够理解我为什么要重构,我绝对不是在搞事情
快速迁移指南
兼容API(必须)️
说明
- show方法快速兼容
SmartDialog.compatible.show();
SmartDialog.compatible.showAttach();
SmartDialog.compatible.showLoading();
SmartDialog.compatible.showToast();
- config快速兼容
SmartDialog.compatible.config;
增加compatible
中间变量,可快速兼容改动的各种参数
快速操作
- 使用全局替换功能快速迁移:
SmartDialog.show
--->SmartDialog.compatible.show
- Mac:command + shift + r
- Windows:ctrl + shift + r
- Config:
SmartDialog.config
--->SmartDialog.compatible.config
- Mac:command + shift + r
- Windows:ctrl + shift + r
参数移除(必须)️
- 4.0版本删除了少量参数
方法 | 说明 |
---|---|
showLoading(...) | 删除background 参数(compatible不兼容该参数) |
showToast(...) | 删除alignment 参数(compatible不兼容该参数) |
showAttach(...) | 删除highlight 参数(compatible兼容该参数) |
- 删除了这些参数,初始化自定义loading和toast的时候,需要做一点点调整
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage,
// here
navigatorObservers: [FlutterSmartDialog.observer],
// here
builder: FlutterSmartDialog.init(
//default toast widget
toastBuilder: (String msg) => CustomToastWidget(msg: msg),
//default loading widget
loadingBuilder: (String msg) => CustomLoadingWidget(msg: msg),
),
);
}
}
说明
background
和alignment
这俩个参数实在没什么用,用到的频率实在太低了
一般都是自定义toast和loading样式,想怎么画就怎么画;如果只是简单用下toast和loading,这俩个参数做不到很强的自定义效果,实在过于累赘,索性删除了
参数名变动(可选)
通过上面兼容API
和参数移除
就可以完整迁移了
这里我将变动的参数名完整的写下,大家可以对照下
原参数名 | 变动参数名 |
---|---|
widget | builder:和路由dialog参数对齐(具体见下面builder参数说明) |
isLoading / isLoadingTemp | animationType:方便后期扩展多种动画类型 |
isPenetrate / isPenetrateTemp | usePenetrate:true(点击事件将穿透背景),false(不穿透) |
isUseAnimation / isUseAnimationTemp | useAnimation:true(使用动画),false(不使用) |
clickBgDismiss / clickBgDismissTemp | clickMaskDismiss:true(点击遮罩后,关闭dialog),false(不关闭) |
animationDuration / animationDurationTemp | animationTime:动画持续时间 |
alignmentTemp | alignment:控制弹窗的位置 |
maskColorTemp | maskColor:遮罩颜色 |
maskWidgetTemp | maskWidget:可高度定制遮罩 |
debounceTemp | debounce:防抖功能 |
builder参数说明(重要)
4.0版本对自定义控件参数做了很大改变
- 老版本
SmartDialog.show(
widget: Container(
height: 80,
width: 180,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(10),
),
alignment: Alignment.center,
child: Text(
'easy custom dialog',
style: TextStyle(color: Colors.white),
),
),
);
- 4.0版本
SmartDialog.show(builder: (context) {
return Container(
height: 80,
width: 180,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(10),
),
alignment: Alignment.center,
child: Text(
'easy custom dialog',
style: TextStyle(color: Colors.white),
),
);
});
这个改动虽然会让使用麻烦了一点,但是有很重要的意义
- 首先是为了和路由dialog的api对齐,路由dialog自定义控件参数也是builder
- 然后解决自定义dialog自身动态刷新问题:自定义布局有TextField,键盘弹起的时候,自定义dialog布局可以动态调整距离(需要使用相应widget)
4.0版本新增功能
强大的Config
- 可以使用config获取dialog是否存在情况
// 自定义dialog,attach或loading,是否存在在界面上
SmartDialog.config.isExist;
// 自定义dialog或attach是否存在在界面上
SmartDialog.config.isExistDialog;
// loading是否存在界面上
SmartDialog.config.isExistLoading;
// toast是否存在在界面上
SmartDialog.config.isExistToast;
- config可以更细致的控制show,showAttach,showLoading,showToast等弹窗
- SmartConfigXxx()默认参数都是我经过深思后设置的,无特殊要求可以不用额外设置
- 如果不需要自定义config数值,下方初始化代码无需写
SmartDialog.config
..custom = SmartConfigCustom()
..attach = SmartConfigAttach()
..loading = SmartConfigLoading()
..toast = SmartConfigToast();
- 可以自定任意config中的数值,以满足相应的需求
- 下方代码是演示自定义参数
- 大家可以按需设置
SmartDialog.config
..custom = SmartConfigCustom(
maskColor: Colors.black.withOpacity(0.35),
useAnimation: true,
)
..attach = SmartConfigAttach(
animationType: SmartAnimationType.scale,
usePenetrate: false,
)
..loading = SmartConfigLoading(
clickMaskDismiss: false,
leastLoadingTime: const Duration(milliseconds: 0),
)
..toast = SmartConfigToast(
intervalTime: const Duration(milliseconds: 100),
displayTime: const Duration(milliseconds: 2000),
);
bindPage
说明
这个参数的含义是将SmartDialog将page绑定:如果在SmartDialog上跳转页面
- 和当前页面绑定SmartDialog会自动隐藏
- 回到绑定页面的时候,SmartDialog将会显示
关于在Dialog上面跳转页面的问题,4.0之前的版本,可以使用useSystem
参数解决
- 使用
useSystem
参数时,本质是使用自带dialog作为载体,这样就可以合理的和page交互 - 但是因为自带dialog的各种局限,使用
useSystem
时:usePenetrate
,tag
,KeepSingle
,permanent
都被禁止使用了
4.0版本引入的bindPage的逻辑,可以避免使用useSystem
时的各种限制
bindPage是默认开启的(可在config中配置),也可以在使用show和showAttach时手动关闭或开启;在特殊的业务场景,按需使用bindPage
和useSystem
即可
使用效果
- 写个演示demo,这个就是正常在弹窗上跳转页面操作
void _dialogBindPage() async {
var index = 0;
Function()? showDialog;
toNewPage(bool useSystem) async {
Get.to(
() {
return Scaffold(
appBar: AppBar(title: Text('New Page ${++index}')),
body: Container(
color: randomColor(),
alignment: Alignment.center,
child: ElevatedButton(
onPressed: () => showDialog?.call(),
child: Text('test bindPage $index'),
),
),
);
},
preventDuplicates: false,
);
}
showDialog = () {
SmartDialog.show(builder: (_) {
return Container(
width: 300,
height: 170,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
child: ElevatedButton(
onPressed: () => toNewPage(false),
child: Text('test bindPage $index'),
),
);
});
};
showDialog();
}
- 来看看效果
- 老实说,没有使用useSystem功能时的效果丝滑
- 但是bindPage也解决了弹窗上跳转页面的问题,同时又保留了usePenetrate,tag,KeepSingle,permanent等功能
- 大家按需使用
关闭弹窗时携带数据
该功能和flutter路由关闭,携带返回数据功能对齐
- 看下demo:点击
show result
按钮,关闭弹窗,并将输入框中的数据返回
void _dialogCarryResult() async {
var result = await SmartDialog.show(
builder: (_) {
var message = '';
return Container(
width: 300,
height: 170,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Container(
width: 100,
margin: EdgeInsets.only(bottom: 30),
child: TextField(onChanged: (msg) => message = msg),
),
ElevatedButton(
onPressed: () => SmartDialog.dismiss(result: message),
child: Text('show result'),
)
]),
);
},
);
SmartDialog.showToast("$result");
}
- 效果
永久化Dialog
将permanent
参数设置成true,打开的dialog将变成永久化dialog,框架内部所做的所有兜底关闭操作(返回事件,路由pop,点击遮罩等)将失效,只能手动关闭
该功能请结合实际业务场景使用,请勿滥用
- 打开一个永久化dialog
SmartDialog.show(
permanent: true,
usePenetrate: true,
builder: (_) => Container(width: 150, height: 150, color: Colors.black),
);
- 关闭永久化dialog
SmartDialog.dismiss(force: true);
- 来看下demo
void _dialogPermanent() async {
openPermanentDialog() {
SmartDialog.show(
permanent: true,
alignment: Alignment.centerRight,
usePenetrate: true,
clickMaskDismiss: false,
builder: (_) {
return Container(
width: 150,
height: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
bottomLeft: Radius.circular(20),
),
boxShadow: [
BoxShadow(color: Colors.grey, blurRadius: 8, spreadRadius: 0.2)
],
),
child: Text('permanent dialog'),
);
},
);
}
SmartDialog.show(builder: (_) {
return Container(
width: 300,
height: 170,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
child: Wrap(spacing: 20, children: [
ElevatedButton(
onPressed: () => openPermanentDialog(),
child: Text('open'),
),
ElevatedButton(
onPressed: () => SmartDialog.dismiss(force: true),
child: Text('close'),
)
]),
);
});
}
- 效果:可以看见pop路由,点击遮罩和返回事件,都不能关闭
permanent dialog
最小加载时间
config中loading中有个leastLoadingTime
参数,可以控制最小的加载时间
这个功能是为了解决接口请求太快,导致loading弹窗一闪而过的问题
- 使用:该参数请结合实际业务场景设置合适的数据,leastLoadingTime默认数值为0秒
- 此处仅做演示,才在此处给config.loading重新赋值,一般建议在app初始化位置就定好参数
- showLoading()之后立马调用dismiss,loading会一闪而过
- 设置了leastLoadingTime为2秒,loading会强制等待俩秒之后,dismiss才会生效
void _loadingLeastTime() async {
SmartDialog.config.loading = SmartConfigLoading(
leastLoadingTime: const Duration(seconds: 2),
);
SmartDialog.showLoading();
SmartDialog.dismiss();
SmartDialog.config.loading = SmartConfigLoading();
}
- 效果
连续toast显示间隔时间
当多个toast连续显示的时候,前一个toast和后一个toast显示无间隔时间,看起来有点突兀
此处在SmartConfigToast
中增加了一个intervalTime
参数,用以控制间隔时间
默认的intervalTime
已经是个合理参数,如无必要,最好不要更改
- 来看下效果,仅做演示,
intervalTime
数值就设置稍微大一些
void _toastIntervalTime() async {
SmartDialog.config.toast = SmartConfigToast(
intervalTime: const Duration(milliseconds: 800),
);
for (var i = 0; i < 3; i++) {
SmartDialog.showToast("toast $i").then((value) {
if (!SmartDialog.config.isExistToast) {
SmartDialog.config.toast = SmartConfigToast();
}
});
}
}
- 效果图
总结
SmartDialog 4.0版本是个非常重要的版本,标志着SmartDialog告别了羞涩,走向了成熟
经过这次重构,我也有了信心,去面对更加复杂的业务场景,进行各种拓展
这次重构我做了很多思考,也非常感谢大家给我提个各种issues
,是你们启发了我!
SmartDialog迁移至4.0:一份真诚的迁移说明的更多相关文章
- Entity Framework Core 2.0 使用代码进行自动迁移
一.前言 我们在使用EF进行开发的时候,肯定会遇到将迁移更新到生产数据库这个问题,前面写了一篇文章介绍了Entity Framework Core 2.0的入门使用,这里面介绍了使用命令生成迁移所需的 ...
- Djang1.8+Python2.0迁移到Django2.0+Python3.6注意事项(转)
Djang1.8+Python2.0迁移到Django2.0+Python3.6注意事项 参考:https://blog.csdn.net/weixin_40475396/article/detail ...
- 工程部署从tomcat6.0迁移到jboss6.0错误总结
2014-11-08 内容存档在evernote,笔记名"工程部署从tomcat6.0迁移到jboss6.0错误总结"
- redis 3.0 集群__数据迁移和伸缩容
添加节点 1,启动2个新的redis-sever, 参照 ( redis 3.0 集群____安装 ),端口号为 7007 和 7008 2,使用命令 redis-trib.rb add-node 命 ...
- 从 ASP.NET Core 3.1 迁移到 5.0
3月中旬,微软官方已经发布了dotnet 5的第一个预览版:5.0.0-preview.1. dotnet core经过前几个版本的发展和沉淀,到3.1已经基本趋于稳定. 所以从.net core 3 ...
- 虚拟机迁移(QEMU动态迁移,Libvirt动(静)态迁移)
动静态迁移的原理 静态迁移是指在虚拟机关闭或暂停的情况下,将源宿主机上虚拟机的磁盘文件和配置文件拷贝到目标宿主机上.这种方式需要显式的停止虚拟机运行,对服务可用性要求高的需求不合适. *** 动态迁移 ...
- sql server迁移数据(文件组之间的互相迁移与 文件组内文件的互相迁移)
转自:https://www.cnblogs.com/lyhabc/p/3504380.html?utm_source=tuicool SQLSERVER将数据移到另一个文件组之后清空文件组并删除文件 ...
- 使用navicat premium将数据库从Oracle迁移到SQL Server,或从Oracle迁移到MySQL
有时候我们有迁移数据库的需求,例如从Oracle迁移到SQL Server,或者从MySQL迁移到Oracle. 很多江湖好汉一时不知如何手工操作,所幸的是Navicat提供了迁移的自动化操作界面. ...
- 怎么将数据库从Oracle迁移到SQL Server,或从Oracle迁移到MySQL
有时候我们有迁移数据库的需求,例如从Oracle迁移到SQL Server,或者从MySQL迁移到Oracle. 很多江湖好汉一时不知如何手工操作,所幸的是Navicat提供了迁移的自动化操作界面. ...
随机推荐
- String 和 StringBuilder、StringBuffer 的区别?
Java 平台提供了两种类型的字符串:String 和 StringBuffer/StringBuilder,它 们可以储存和操作字符串.其中 String 是只读字符串,也就意味着 String 引 ...
- promethues常用的函数
prometheus函数常用 时数据 (Instant vector): 包含一组时序,每个时序只有一个点,例如:http_requests_total区间数据 (Range vector): 包含一 ...
- C++“拷贝构造函数”和“等号重载”有什么区别?
CTypeA(const CTypeB& b)CTypeA& operator=(const CTypeB& b)一直没弄懂这两个有什么区别.只知道,重载了=号,下面复制的时候 ...
- Python的数据基础库Numpy怎样对数组进行排序
Numpy怎样对数组排序 Numpy给数组排序的三个方法: numpy.sort:返回排序后数组的拷贝 array.sort:原地排序数组而不是返回拷贝 numpy.argsort:间接排序,返回的是 ...
- 前端进阶(8) - 前端开发需要了解的工具集合:webpack, eslint, prettier, ...
前端开发需要了解的工具集合:webpack, eslint, prettier, ... 前端开发需要了解的一些工具,这些工具能够帮助你在项目开发中事半功倍. 1. nrm: npm registry ...
- 小白上学のcanvas零基础
<canvas> 元素 <canvas> 看起来和 <img> 元素很相像,唯一的不同就是它并没有 src 和 alt 属性.实际上,<canvas> ...
- mpvue 如何使用腾讯视频插件?
1.在小程序微信开放平台:设置 --- 第三方服务里,申请腾讯视频插件2.申请成功后就可以在项目中使用了 具体使用步骤如下:1.在项目目录src下的main.js中加入下面代码,这里代码会被编译到ap ...
- Struts2-拦截器原理
拦截器原理包含Aop思想和责任链模式 1.Aop思想 aop是面向切面编程,有基本功能,扩展功能,不通过修改源代码方式扩展功能.(动态代理) 2.责任链模式,Java有23种设计模式,责任链模式是其中 ...
- ORM中聚合函数、分组查询、Django开启事务、ORM中常用字段及参数、数据库查询优化
聚合函数 名称 作用 Max() 最大值 Min() 最小值 Sum() 求和 Count() 计数 Avg() 平均值 关键字: aggregate 聚合查询通常都是配合分组一起使用的 关于数据库的 ...
- jdk-1.8环境变量配置
1.首先下载好jdk-1.8的安装包. 这个安装也是傻瓜式安装,一直下一步即可.一定要记得中间你所设置的安装路径 2.切记 切记 jdk的安装路径 ! 3.右键"此电脑",点击最下 ...