Flutter 知识集锦 | extension 拓展类方法

Dart 的拓展类方法已经支持很久了,之前忘了写篇文章介绍一下。最近写了几个拓展方法,借此机会,好好介绍一下 extension 关键字对类的拓展。


1. 从密文的字符串开始说起

比如现在有个需求:

将一个长度大于 4 的字符串,仅保留首尾两个字符,进行密文展示。

比如 1981462002 -> 19******02

很容易可以想到,定义一个 hide 方法,输入一个字符串,进行处理后,输出目标字符串。处理逻辑如下:

dart 复制代码
void main(){
  String num = "1981462002";
  String ret = hide(num);
  print(ret); // 19******02
}

String hide(String src){
  String p0 = src.substring(0, 2);
  String p1 = List.filled(src.length - 4, '*').join();
  String p2 = src.substring(src.length-2);
  return "$p0$p1$p2";
}

上面通过 hide(num) 来调用方法,获得结果字符串。但是这种全局方法单独放置比较零散,维护起来有点麻烦。Dart 中提供了 extension 关键字拓展类方法,可以为一个类附加额外的方法.

通过 extension [name] on [type] 的语法定义 type 类型的拓展方法。如下所示,拓展 String 类型时,将之前的 hide 逻辑放入其中即可。此时 hide 方法可以访问 String 类中的公开成员和方法:

dart 复制代码
extension TolyStringExt on String {
  String hide(){
    String p0 = substring(0, 2);
    String p1 = List.filled(length - 4, '*').join();
    String p2 = substring(length-2);
    return "$p0$p1$p2";
  }
}

这样 hide 成为 String 类型对象的成员方法,其优势在于:

  • 1\]. 可以以增强某类型功能为目的,将某个函数收编,提供居住场所,不至于流落在外。

  • 3\]. 一般拓展方法,在书写上更加简洁,拓展的方法,可以共享复用。

下面对 hide 方法进行优化,支持自定义密文字符,首尾保留的长度,以及字符串长短的校验。你也可以封装其他关于字符串的实用方法,比如一些邮箱、密码正则的校验。

dart 复制代码
extension TolyStringExt on String {
  String hide({
    String fix = "*",
    int start = 2,
    int end = 2,
  }) {
    if (length <= start) {
      return this;
    }
    String p0 = substring(0, start);
    int hideCount = length - start - end;
    if (hideCount <= 0) {
      return p0.padRight(length, fix);
    }
    String p1 = List.filled(length - (start + end), fix).join();
    String p2 = substring(length - end);
    return "$p0$p1$p2";
  }
}

2. BuildContext 的拓展方法

Flutter 中 BuildContext 是一个非常重要对象,它作为 Element 的顶层接口,负责维护构建过程中的上下文信息,可以通过它来向上层查找元素节点、访问渲染对象。很多状态管理、路由的类库中,都可以看到对它复写的身影。这里以一个简单的 Snack 弹框为例,看一下对 BuildContext 的拓展。

成功 提醒

如下所示,这是以前对 Toast 的简单封装,使用静态方法来简化调用,将 BuildContext 作为入参传入其中。并提供三种颜色作为成功、失败、警告三种场景的背景色:

dart 复制代码
import 'package:flutter/cupertino.dart';

class Toast{
 static void success(BuildContext context,String msg){
   toast(context, Colors.green, msg);
  }

 static void error(BuildContext context,String msg){
    toast(context, Colors.red, msg);
  }

 static  void warning(BuildContext context,String msg){
    toast(context, Colors.orange, msg);
  }

 static void toast(BuildContext context,Color color,String msg){
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        backgroundColor: color, content: Text(msg)));
  }
}

方法调用如下:

dart 复制代码
Toast.warning(context,'当前领域秘钥未修改,无需提交');

可以通过拓展 BuildContext 来简化,将 toast 视为 BuildContext 的能力,在调用时将会更简洁:

dart 复制代码
import 'package:flutter/material.dart';

extension ToastContext on BuildContext {

  void toast(Color color, String msg) {
    ScaffoldMessenger.of(this).showSnackBar(
      SnackBar(backgroundColor: color, content: Text(msg)),
    );
  }

  void warning(String msg) => toast(Colors.orange, msg);

  void error(String msg) => toast(Colors.red, msg);

  void success(String msg) => toast(Colors.green, msg);
}

3. 其他三方库对 BuildContext 的拓展

provider 中的 read、 watch、select 等操作,是对 BuildContext 的拓展,可以更方便地通过上下文调用的方式访问提供器:

dart 复制代码
extension ReadContext on BuildContext {
  T read<T>() {
    return Provider.of<T>(this, listen: false);
  }
}

extension WatchContext on BuildContext {
  T watch<T>() {
    return Provider.of<T>(this);
  }
}


extension SelectContext on BuildContext {
    R select<T, R>(R Function(T value) selector) {...}
}

go_router 中的 push、pop、go 等一系列方法,也是对 BuildContext 的拓展,可以更方便的通过 BuildContext 对象触发方法,来操作路由的变化:


总的来看,拓展方法可以让作为入参的某个对象拥有 主动权,作为该类型的附加方法,可以达到简化调用的目的。不过拓展方法虽好,可不要贪杯哦,肆意的拓展,可能会使代码很难让别人读懂,这点和运算符的重载类似。以语义为准绳,不要为了炫技而覆写或拓展。那本文就到这里,谢谢观看 ~

相关推荐
张拭心9 分钟前
春节后,有些公司明确要求 AI 经验了
android·前端·人工智能
张拭心19 分钟前
Android 17 来了!新特性介绍与适配建议
android·前端
shankss1 小时前
Flutter 下拉刷新库 pull_to_refresh_plus 设计与实现分析
flutter
Kapaseker3 小时前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
黄林晴3 小时前
Android17 为什么重写 MessageQueue
android
忆江南17 小时前
iOS 深度解析
flutter·ios
明君8799718 小时前
Flutter 实现 AI 聊天页面 —— 记一次 Markdown 数学公式显示的踩坑之旅
前端·flutter
恋猫de小郭19 小时前
移动端开发稳了?AI 目前还无法取代客户端开发,小红书的论文告诉你数据
前端·flutter·ai编程
MakeZero21 小时前
Flutter那些事-交互式组件
flutter
shankss21 小时前
pull_to_refresh_simple
flutter