前言
一个开源库,随着一直的迭代优化,难免会遇到一个很苦楚的问题
- 最后的设计并不是很正当:想增加的很多新性能都受此掣肘
想使得该库更加的弱小和强壮,必须要做一个重构
- 因为重构波及到对外裸露的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
,是你们启发了我!
发表回复