往期优选推荐
1. Fam 最简单的 Flutter 项目 Assets 管理脚本服务
推荐指数: ⭐️⭐️⭐️⭐️⭐️
》fam 和 flutter_gen 相比优点《
-
fam
不需要在项目的pubspec.yaml
文件的dev_dependencies
引入任何东西;而flutter_gen
需要引入flutter_gen_runner
。 -
fam
在导入资源后只需要执行fam run
即可;而flutter_gen
需要执行dart run build_runner build
。需要注意的是dart run build_runner build
是很多代码自动生成的运行指令(多语言、json解析、rividerpod...等)。所以一旦执行就需要很长时间才能完成,而fam
拥有独立的体系,便捷快速! -
fam
的资源管理类在项目中使用简短;而flutter_gen
需要使用.
语法一直到资源文件,然后再通过.path
获取资源路径,这很麻烦! -
fam
拥有独立的系统体系;flutter_gen
和多语言的使用有一定的冲突。
2. dev_prokit 全部功能目录
推荐指数: ⭐️⭐️⭐️⭐️⭐️
该篇文章包含了 dev_prokit 所有功能介绍和示例的目录。此文章能够让开发者快速的了解 dev_prokit 都提供了那些功能,以及能更快速的找到自己需要的功能介绍和应用。
本期功能介绍
一、起因
在近期公司项目的优化升级过程中,当我们将Flutter版本从3.13.6
升级到3.19.6
时,我们不幸地发现了一个显著的变动:WillPopScope
这一组件被标记为已废弃。具体的提示信息如下所示:
将鼠标放在 WillPopscope
上就会出现提示如下:
上面的提示的意思是 : 在 v3.12.0-1.0.pre 版本之后 WillPopScope.new 已弃用,不应使用,请改用 PopScope
。那么,关于 PopScope 的奥秘,它究竟蕴含了哪些参数与独特的方法?我们又该如何巧妙地运用它呢?接下来,就让我们一起踏上这场探索之旅吧。
二、 PopScope 详解
-
PopScope
源码c++const PopScope({ super.key, required this.child, this.canPop = true, this.onPopInvoked, }); final Widget child; final PopInvokedCallback? onPopInvoked; final bool canPop;
从上图源码看 PopScope 有四个属性相比 WillPopScope 多了一个属性。下面我们介绍 PopScope 属性。
-
PopScope
属性介绍-
Key? key
PopScope 组件的唯一标识。
-
Widget child
树中此小部件(PopScope)下方的小部件(child)。
-
PopInvokedCallback? onPopInvoked
该属性方法是在处理路由弹出后调用。
📢 注意: 调用此方法不能阻止路由弹出,因为该方法是在路由弹出后调用的。
-
bool canPop
该属性是设置是否阻止当前路由弹出。为 false 时阻止路由弹出。
📢 注意:如果路由的子树中出现多个 PopScope 组件,则要每个 canPop 都为 true 时才可以返回。
-
三、 PopScope 应用思路
PopScope 的应用起始也很简单,大致步骤如下:
- 首先 : 确认该页面是否返回拦截, 需要拦截就将 PopScope 的
canPop
设置为false
,否则 PopScope 组件就无需添加; - 其次 : 实现 PopScope 的
onPopInvoked
方法,在该方法里面编写阻止弹出的逻辑; - 然后 : 在阻止弹出逻辑中,要判断满足什么条件需要阻止路由弹出以及什么条件下不需要阻止路由弹出, 在满足不需要阻止路由弹出的条件后调用
Navigator.of(context).pop()
或者你自定义的路由返回方法即可。
从上面的大致步骤看, PopScope 实现路由返回拦截是不是很简单!
四、PopScope 应用示例
-
场景 1
通过按钮跳转到一个页面,该页面有一个输入框。在导航返回时,如果输入框为空,则直接退出;如果输入框不为空,则需要弹出二次确认框询问是否退出该页面。如果用户选择
取消
,则不退出当前页面;如果选择确定
,则退出当前页面。 -
代码如下
c++final TextEditingController textEditingController = TextEditingController(); PopScope( canPop: false, onPopInvoked: (didPop) async { if (textEditingController.text.isNotEmpty) { final result = await showDialog( context: context, builder: (context) { return Center( child: Row( children: [ IconButton( onPressed: () { appRouter.pop(false); }, icon: Text('取消'), ), IconButton( onPressed: () { appRouter.pop(true); }, icon: Text('确定'), ) ], ), ); }, ); if (result ?? false) { appRouter.pop(); } } }
上面代码实现了阻止导航返回功能。但是其中有个不友好的体验,那就是当
canPop
为false
时,Ios 和 Android 的侧滑返回就不能使用了。如果想使用侧滑功能那么我们就需要动态的更改canPop
的值。 -
PopScope 需要保留 Ios 、 Android 侧滑功能 (扩展)
要使用 PopScope 保留侧滑功能需要将
canPop
参数设置为true
。 示例如下:c++StreamController streamController = StreamController(); StreamBuilder( initialData: true, stream: streamController.stream, builder: (context, snapshot) { return PopScope( canPop: snapshot.data ?? true, onPopInvoked: (didPop) async { if (didPop == false) { final result = await showDialog( context: context, builder: (context) { return Center( child: Row( children: [ IconButton( onPressed: () { appRouter.pop(false); }, icon: Text('取消'), ), IconButton( onPressed: () { appRouter.pop(true); }, icon: Text('确定'), ) ], ), ); }, ); if (result ?? false) { appRouter.pop(); } } }, child: TextField( onChanged: (value) => streamController.add(value.isEmpty), ), ); }, }
这样就可以使用侧滑功能以及二次弹框逻辑。这种模式会导致根部树进行
build
也有可能导致页面数据出现重置情况。这种情况可以使用Key? key
进行优化。示例代码如下:c++PopScope( canPop: true, onPopInvoked: (didPop) {//... 省略} child: TextField( key: ValueKey('Only one!'), onChanged: (value) => streamController.add(value.isEmpty), ), )
五、 PopScope 目前存在问题
PopScope
目前在 导航 1.0
使用表现还是可以的,但是在 导航 2.0
以及一些第三方插件 go_router
应用中出现一些 onPopInvoked
方法可以回调又是不回调的情况,相关问题可以关注这个话题,链接如下: PopScope seems to be incompatible with GoRouter 。
六、鼓励与支持
这便是 dev_prokit 提供的方法之一。以编写代码较少、功能完善、代码运行强壮、支持面广等形式来开发 dev_prokit 包。 如果你有 Idea
或者 Opinion
,那请你点击此处 》》Idea & Opinion《《 把它留下吧!如果你在使用该功能后感觉还可以,它能够给你的项目开发带来便捷,那请你为之点个⭐️ dev_prokit ⭐️ 吧!分享给更多需要它的开发者。