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 对象触发方法,来操作路由的变化:


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

相关推荐
_一条咸鱼_3 小时前
揭秘 Android View 位移原理:源码级深度剖析
android·面试·android jetpack
_一条咸鱼_3 小时前
深度剖析:Android View 滑动原理大揭秘
android·面试·android jetpack
_一条咸鱼_3 小时前
深度揭秘:Android View 滑动冲突原理全解析
android·面试·android jetpack
_一条咸鱼_3 小时前
揭秘 Android View 惯性滑动原理:从源码到实战
android·面试·android jetpack
ansondroider4 小时前
Android adb 安装应用失败(安装次数限制)
android·adb·install
肥肥呀呀呀4 小时前
flutter getx 中.obs 的方法refresh方法
flutter
只可远观4 小时前
Flutter 泛型 泛型方法 泛型类 泛型接口
服务器·windows·flutter
肥肥呀呀呀4 小时前
ipa包安装到apple手机上
flutter
艾小逗5 小时前
uniapp中检查版本,提示升级app,安卓下载apk,ios跳转应用商店
android·ios·uni-app·app升级