Flutter的弹窗阻拦器
前语
弹窗的排队执行在App中是一个很常见的运用场景。比如进入App主页,一系列的弹窗就会弹出。假如不做处理就会导致弹窗一窝蜂的悉数弹出,严重影响用户体会。
假如多个弹窗中有判别逻辑,同意协议弹出另一个弹窗,不同意弹窗别的一个弹窗,又添加了复杂度了。
所以才会有需求管理多个弹窗的展现机遇,一般来说在一个Flutter App 中有下面几种方法来管理的。
一、行列的方法完结
其实最简略最原始的计划便是硬写,判别逻辑写在弹窗或Picker里面,一层一层的嵌套,横竖布局都嵌套了,弹窗逻辑嵌套怕什么…
当然比较好的做法是用一个行列管理起来。
class DialogQueue {
final Queue<AlertDialog> _dialogQueue = Queue();
bool _isShowingDialog = false;
void show(AlertDialog dialog, BuildContext context) {
_dialogQueue.add(dialog);
if (!_isShowingDialog) {
_isShowingDialog = true;
_showNext(context);
}
}
void _showNext(BuildContext context) {
if (_dialogQueue.isNotEmpty) {
final dialog = _dialogQueue.removeFirst();
showDialog<void>(
context: context,
builder: (BuildContext context) {
return dialog;
},
).then((_) {
if (_dialogQueue.isNotEmpty) {
_showNext(context);
} else {
_isShowingDialog = false;
}
});
}
}
}
运用的时分,往行列里面添加即可:
ElevatedButton(
onPressed: () {
_dialogQueue.show(
AlertDialog(
title: Text('Dialog 1'),
content: Text('This is the first dialog'),
),
context,
);
},
child: Text('Show Dialog 1'),
),
ElevatedButton(
onPressed: () {
_dialogQueue.show(
AlertDialog(
title: Text('Dialog 2'),
content: Text('This is the second dialog'),
),
context,
);
},
child: Text('Show Dialog 2'),
),
代码很简略,但这样尽管能做到排队执行,但是有几个很大的问题,不行灵敏,不能操控其中哪一个不显示或不显示(完结起来比较麻烦),其次便是只支撑 Dialog,不支撑用 Toast SnackBar Picker等其他的用法。
总结一句话便是不行灵敏。那么咱们之前运用过值阻拦式的阻拦器完结在 Android 渠道已经完结过了。那么咱们移植到 Flutter 渠道能不能完结对应的功能呢?
二、阻拦器的方法完结
与前文阻拦器完结登录阻拦的方法有所区别的是经过值传递方法咱们需求界说一个泛型,把传递的目标界说一下。
class InterceptChain<T> {
InterceptChain? next;
void intercept(T data) {
next?.intercept(data);
}
}
管理类:
class InterceptChainHandler<T> {
InterceptChain? _interceptFirst;
void add(InterceptChain interceptChain) {
if (_interceptFirst == null) {
_interceptFirst = interceptChain;
return;
}
InterceptChain? node = _interceptFirst;
while (true) {
if (node!.next == null) {
node.next = interceptChain;
break;
}
node = node.next;
}
}
void intercept(T data) {
_interceptFirst?.intercept(data);
}
}
与之前阻拦登录的方法不同的是,这种计划没有指定的一些阻拦器,愈加的灵敏,运用起来咱们就需求界说每一个 InterceptChain ,也便是每一个 Dialog/Picker等作用都能够是一个 Intercept 。
class TipsIntercept extends InterceptChain<DialogPass> {
@override
void intercept(DialogPass data) {
SmartDialog.show(
usePenetrate: false,
builder: (context) =>
AppDefaultDialog(
"你确认要发送验证码吗?",
confirmAction: () {
super.intercept(data);
},
),
);
}
}
class VerifyIntercept extends InterceptChain<DialogPass> {
@override
void intercept(DialogPass data) {
SmartDialog.show(
usePenetrate: false,
builder: (context) => VerifyCodeDialog(
confirmAction: () {
super.intercept(data);
},
),
);
}
}
class OneIntercept extends InterceptChain<DialogPass> {
@override
void intercept(DialogPass data) {
if (data != null) {
final interceptData = '当时的Data1:${data.msg}';
print(interceptData);
if (data.passType == 1) {
// 弹窗1
SmartDialog.show(
usePenetrate: false,
builder: (context) => AppDefaultDialog(
data.msg ?? "",
confirmAction: () {
data.passType = 2;
super.intercept(data);
},
),
);
} else {
super.intercept(data);
}
} else {
super.intercept(data);
}
}
}
class TwoIntercept extends InterceptChain<DialogPass> {
@override
void intercept(DialogPass data) {
if (data != null) {
final interceptData = '当时的Data2:${data.msg}';
print(interceptData);
if (data.passType == 2) {
// 弹窗2
SmartDialog.show(
usePenetrate: false,
clickMaskDismiss: false,
builder: (context) => PrivacyPolicyDialog(
confirmAction: () {
data.passType = 3;
super.intercept(data);
},
cancelAction: () {
super.intercept(data);
},
),
);
} else {
super.intercept(data);
}
} else {
super.intercept(data);
}
}
}
class ThreeIntercept extends InterceptChain<DialogPass> {
@override
void intercept(DialogPass data) {
if (data != null) {
final interceptData = '当时的Data3:${data.msg}';
print(interceptData);
if (data.passType == 3) {
// 弹窗2
DataPickerUtil.showCupertinoDataPicker(
items: ["悉数","等候承认", "已完结"],
onPickerChanged: (list, position) {
super.intercept(data);
},
);
} else {
super.intercept(data);
}
} else {
super.intercept(data);
}
}
}
这里简略的界说了5个弹窗/Picker作用,而且简略的界说了变量的操控目标为:
class DialogPass {
String? msg;
int passType = 0;
DialogPass(this.msg, this.passType);
}
这个是一般是由后台服务器操控,请求接口之后能够动态的依据多个变量操控哪一个弹窗展现,而且能够操控一个弹窗展现之后它对应的后续弹窗的展现。能够很便利的经过目标中的变量操控。
详细哪个弹窗是否展现,如何展现都是子 Intercept 操控,咱们终究只需求把悉数的阻拦类添加到阻拦器容器中即可:
final intercepts = InterceptChainHandler<DialogPass>();
intercepts.add(TipsIntercept());
intercepts.add(VerifyIntercept());
intercepts.add(OneIntercept());
intercepts.add(TwoIntercept());
intercepts.add(ThreeIntercept());
intercepts.intercept(DialogPass('你确认你要阅读悉数协议吗1?',1));
作用:
尽管代码是多一个但是相对而言就灵敏一点。
跋文
用行列尽管也能完结一些特定的场景需求,但是我仍是更推荐阻拦器的方法,相对而言更灵敏。
所以说一些在 iOS/Android 中成熟运用的一些规划形式真的是能够很便利的解决一些事务场景的痛点,并不约束于言语与渠道。
现在咱们运用中的主页的弹窗与请求作业的弹窗校验就能很便利的用阻拦器的方法进行管理了。而且用值传递的方法咱们也能够很便利的把终究处理过后的数据拿到能够进行其他的阻拦或操作。
代码比较简略都已经在文中贴出。后期我也会继续更新一些其他的规划形式在 Flutter 项目中的运用,还有一些实在开发场景中一些坑点与踩坑经历,大家能够重视一下。
我在 Flutter 运用方面仍是一个新手来着,假如本文的解说有什么讹夺的当地,希望同学们一定要指出哦。有疑问也能够谈论区交流学习前进,感谢!
当然假如觉得本文还不错对你有些协助的话,还请点赞
支撑一下哦,你的支撑是我最大的动力啦!
Ok,这一期就此完结。