Flutter扩展功能插件dartx的使用

发布于 1周前 作者 nodeper 来自 Flutter

Flutter扩展功能插件dartx的使用

简介

dartx 是一个为 Dart 语言提供的扩展库,它为 Dart 的核心类型(如 int, String, List 等)添加了许多实用的方法。这些扩展方法可以简化代码编写,使代码更加简洁和易读。

DartX Logo

Dart CI Codecov Pub Package Pub Package

如果你需要某个扩展方法而当前版本中没有提供,请随时在 GitHub 上提出问题或提交 Pull Request

资源

快速开始 🎉

安装

在你的 pubspec.yaml 文件中添加以下依赖:

dependencies:
  dartx: any

然后在 Dart 文件中导入库:

import 'package:dartx/dartx.dart';

Iterable 扩展

.slice()

返回索引在 start(包含)和 end(包含)之间的元素。

final list = [0, 1, 2, 3, 4, 5];
final last = list.slice(-1); // [5]
final lastHalf = list.slice(3); // [3, 4, 5]
final allButFirstAndLast = list.slice(1, -2); // [1, 2, 3, 4]

.sortedBy() & .thenBy()

按多个属性对列表进行排序。

class Dog {
  final String name;
  final int age;

  Dog({required this.name, required this.age});
}

void main() {
  final dogs = [
    Dog(name: "Tom", age: 3),
    Dog(name: "Charlie", age: 7),
    Dog(name: "Bark", age: 1),
    Dog(name: "Cookie", age: 4),
    Dog(name: "Charlie", age: 2),
  ];

  final sorted =
      dogs.sortedBy((dog) => dog.name).thenByDescending((dog) => dog.age);
  // Bark, Cookie, Charlie (7), Charlie (2), Tom
}

.distinctBy()

从列表中获取唯一的元素。

final words = ['this', 'is', 'a', 'test'];
final distinctByLength = words.distinctBy((it) => it.length); // ['this', 'is', 'a']

.flatten()

将嵌套的列表展平为一个新的可迭代对象。

final nestedList = [[1, 2, 3], [4, 5, 6]];
final flattened = nestedList.flatten(); // [1, 2, 3, 4, 5, 6]

.chunkWhile() & .splitWhen()

根据条件分块或分割列表。

final list = [1, 2, 4, 9, 10, 11, 12, 15, 16, 19, 20, 21];
final increasingSubSequences = list.chunkWhile((a, b) => a + 1 == b);

// increasingSubSequences = [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]

int 扩展

.buildString()

通过 StringBuffer 构建新的字符串。

final word = buildString((sb) {
  for (var i = 0; i < 10; i++) {
    sb.write(i);
  }
});
// 0123456789

.ordinal

返回整数的序数形式。

final a = 1.ordinal();  // 1st
final b = 108.ordinal();  // 108th

String 扩展

.capitalize

将字符串的第一个字母大写。

final word = 'abcd'.capitalize(); // Abcd
final anotherWord = 'Abcd'.capitalize(); // Abcd

.decapitalize

将字符串的第一个字母小写。

final word = 'abcd'.decapitalize(); // abcd
final anotherWord = 'Abcd'.decapitalize(); // abcd

.isAscii

检查字符串是否为 ASCII 编码。

final isAscii = 'abc123 !,.~'.isAscii; // true
final isNotAscii = '§3'.isAscii; // false

.isBlank

检查字符串是否为空白或仅包含空格。

final notBlank = '   .'.isBlank; // false
final blank = '  '.isBlank; // true

.isDouble

检查字符串是否可以解析为 double 类型。

final a = ''.isDouble; // false
final b = 'a'.isDouble; // false
final c = '1'.isDouble; // true
final d = '1.0'.isDouble; // true
final e = '123456789.987654321'.isDouble; // true
final f = '1,000'.isDouble; // false

.isInt

检查字符串是否可以解析为 int 类型。

final a = ''.isInt; // false
final b = 'a'.isInt; // false
final c = '1'.isInt; // true
final d = '1.0'.isInt; // false
final e = '1,000'.isInt; // false

.isLatin1

检查字符串是否为 Latin1 编码。

final isLatin1 = '§Êü'.isLatin1; // true
final isNotLatin1 = 'ő'.isLatin1; // false

.isLowerCase

检查字符串是否全部为小写字母。

final a = 'abc'.isLowerCase; // true
final b = 'abC'.isLowerCase; // false
final c = '   '.isLowerCase; // true
final d = ''.isLowerCase; // false

.isNotBlank

检查字符串是否不为空且包含非空白字符。

final blank = '  '.isNotBlank; // false
final notBlank = '   .'.isNotBlank; // true

.isNullOrEmpty

检查字符串是否为 null 或空。

final isNull = null.isNullOrEmpty; // true
final isEmpty = ''.isNullOrEmpty; // true
final isBlank = ' '.isNullOrEmpty; // false
final isLineBreak = '\n'.isNullOrEmpty; // false

.isNotNullOrEmpty

检查字符串是否既不是 null 也不是空。

final isNull = null.isNullOrEmpty; // true
final isEmpty = ''.isNullOrEmpty; // true
final isBlank = ' '.isNullOrEmpty; // false
final isLineBreak = '\n'.isNullOrEmpty; // false

.isNullOrBlank

检查字符串是否为 null 或空白。

final isNull = null.isNullOrBlank; // true
final isEmpty = ''.isNullOrBlank; // true
final isBlank = ' '.isNullOrBlank; // true
final isLineBreak = '\n'.isNullOrBlank; // true
final isFoo = ' foo '.isNullOrBlank; // false

.isNotNullOrBlank

检查字符串是否既不是 null 也不是空白。

final isNull = null.isNullOrBlank; // true
final isEmpty = ''.isNullOrBlank; // true
final isBlank = ' '.isNullOrBlank; // true
final isLineBreak = '\n'.isNullOrBlank; // true
final isFoo = ' foo '.isNullOrBlank; // true

.isUpperCase

检查字符串是否全部为大写字母。

final a = 'ABC'.isUpperCase; // true
final b = 'ABc'.isUpperCase; // false
final c = '   '.isUpperCase; // true
final d = ''.isUpperCase; // false

.md5

计算 MD5 哈希值并返回十六进制字符串。

final a = 'abc'.md5; // 900150983cd24fb0d6963f7d28e17f72
final b = 'ഐ⌛酪Б👨‍👨‍👧‍👦'.md5; // c7834eff7c967101cfb65b8f6d15ad46

.urlEncode

将字符串转换为 URL 编码格式。

const originalUrl = 'Hello Ladies + Gentlemen, a signed OAuth request!';
final encodedUrl = originalUrl.urlEncode;
// 'Hello%20Ladies%20+%20Gentlemen,%20a%20signed%20OAuth%20request!'

.urlDecode

解码 URL 编码的字符串。

const encodedUrl = 'Hello%20Ladies%20+%20Gentlemen,%20a%20signed%20OAuth%20request!';
final decodedUrl = encodingUrl.urlDecode;
// 'Hello Ladies + Gentlemen, a signed OAuth request!'

.removePrefix(), .removeSuffix() 和 .removeSurrounding()

移除字符串的前缀、后缀或同时移除前后缀。

final name = 'James Bond'.removePrefix('James '); // Bond
final milliseconds = '100ms'.removeSuffix('ms'); // 100
final text = '&lt;p&gt;Some HTML&lt;/p&gt;'
  .removeSurrounding(prefix: '&lt;p&gt;', suffix: '&lt;/p&gt;'); // Some HTML

.reversed

返回反转后的字符串。

final emptyString = ''.reversed; // ''
final reversed = 'abc🤔'.reversed; // '🤔cba'

.slice()

返回一个新的子字符串,包含从 startend 的字符。

final sliceOne = 'awesomeString'.slice(0, 6)); // awesome
final sliceTwo = 'awesomeString'.slice(7)); // String

.toDoubleOrNull()

尝试将字符串解析为 double 类型,失败时返回 null。

final numOne = '1'.toDoubleOrNull(); // 1.0
final numTwo = '1.2'.toDoubleOrNull(); // 1.2
final blank = ''.toDoubleOrNull(); // null

.toInt()

尝试将字符串解析为 int 类型,默认基数为 10,解析失败时抛出 FormatException

final a = '1'.toInt(); // 1
final b = '100'.toInt(radix: 2); // 4
final c = '100'.toInt(radix: 16); // 256
final d = '1.0'.toInt(); // throws FormatException

.toIntOrNull()

尝试将字符串解析为 int 类型,失败时返回 null。

final number = '12345'.toIntOrNull(); // 12345
final notANumber = '123-45'.toIntOrNull(); // null

.toUtf8()

将字符串转换为 UTF-8 编码。

final emptyString = ''.toUtf8(); // []
final hi = 'hi'.toUtf8(); // [104, 105]
final emoji = '😄'.toUtf8(); // [240, 159, 152, 132]

.toUtf16()

将字符串转换为 UTF-16 编码。

final emptyString = ''.toUtf16(); // []
final hi = 'hi'.toUtf16(); // [104, 105]
final emoji = '😄'.toUtf16(); // [55357, 56836]

.orEmpty()

如果字符串为 null,则返回空字符串,否则返回原字符串。

String? nullableStr;
final str = nullableStr.orEmpty(); // ''

.matches()

检查字符串是否匹配给定的正则表达式。

print('as'.matches(RegExp('^.s\$'))) // true
print('mst'.matches(RegExp('^.s\$'))) // false

Time utils

dartx 导入了 time.dart 包,提供了更多的时间处理方法。

int secondsInADay = 1.days.inSeconds;

Duration totalTime = [12.5.seconds, 101.milliseconds, 2.5.minutes].sum();

DateTime oneWeekLater = DateTime.now() + 1.week;

num 扩展

.coerceIn()

确保数值在指定范围内。

final numberInRange = 123.coerceIn(0, 1000); // 123
final numberOutOfRange = -123.coerceIn(0, 1000); // 0

.toBytes()

将数值转换为二进制形式。

.toChar()

将数值转换为字符。

final character = 97.toChar(); // a

range 扩展

rangeTo

创建两个整数之间的范围(向上、向下或自定义步长)。

// 向上,默认步长为 1
for (final i in 1.rangeTo(5)) {
  print(i); // 1, 2, 3, 4, 5
}
// 向下,自定义步长
for (final i in 10.rangeTo(2).step(2)) {
  print(i); // 10, 8, 6, 4, 2
}

Function 扩展

.partial(), .partial2() …

部分应用函数的参数,并返回一个接受剩余参数的新函数。

void greet(String firstName, String lastName) {
  print('Hi $firstName $lastName!');
}

final greetStark = greet.partial('Stark');
greetStark('Sansa'); // Hi Sansa Stark!
greetStark('Tony'); // Hi Tony Stark!

File 扩展

.name

获取文件的名称和扩展名。

final file = File('some/path/testFile.dart');
print(file.name); // testFile.dart
print(file.nameWithoutExtension); // testFile

.appendText()

向文件追加文本。

await File('someFile.json').appendText('{test: true}');

.isWithin()

检查文件是否在某个目录内。

final dir = Directory('some/path');
File('some/path/file.dart').isWithin(dir); // true

Directory 扩展

.file(String)

引用目录中的文件。

Directory androidDir = Directory('flutter-app/android');
File manifestFile = androidDir.file("app/src/main/AndroidManifest.xml");

.directory(String)

引用目录中的子目录。

Directory androidDir = Directory('flutter-app/android');
Directory mainSrc = androidDir.directory("app/src/main");

.contains(FileSystemEntity entity, {bool recursive = false})

检查目录是否包含某个文件系统实体(文件或目录)。可以通过 recursive 参数包含子目录。

final File someFile = File('someFile.txt');
final Directory someDir = Directory('some/dir');

final Directory parentDir = Directory('parent/dir');

parentDir.contains(someFile);
parentDir.contains(someDir);
parentDir.contains(someFile, recursive: true);
parentDir.contains(someDir, recursive: true);

.containsSync(FileSystemEntity entity, {bool recursive = false})

.contains() 相同,但为同步方法,返回布尔值。

License

Copyright 2019 Simon Leier

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

示例代码

以下是完整的示例代码,展示了如何使用 dartx 库中的扩展方法:

// ignore_for_file: unused_local_variable
import 'package:dartx/dartx.dart';

void main() {
  final list = [0, 1, 2, 3, 4, 5];
  final last = list.slice(-1); // [5]
  final lastHalf = list.slice(3); // [3, 4, 5]
  final allButFirstAndLast = list.slice(1, -2); // [1, 2, 3, 4]

  final dogs = [
    Dog(name: 'Tom', age: 3),
    Dog(name: 'Charlie', age: 7),
    Dog(name: 'Bark', age: 1),
    Dog(name: 'Cookie', age: 4),
    Dog(name: 'Charlie', age: 2),
  ];

  final sorted =
      dogs.sortedBy((dog) => dog.name).thenByDescending((dog) => dog.age);
  // Bark, Cookie, Charlie (7), Charlie (2), Tom

  final words = ['this', 'is', 'a', 'test'];
  final distinctByLength =
      words.distinctBy((it) => it.length); // ['this', 'is', 'a']

  final nestedList = [
    [1, 2, 3],
    [4, 5, 6]
  ];
  final flattened = nestedList.flatten(); // [1, 2, 3, 4, 5, 6]

  123.0.minus(null); // 123.0
}

class Dog {
  final String name;
  final int age;

  Dog({required this.name, required this.age});
}

通过上述内容,你可以快速了解并使用 dartx 提供的各种扩展方法,从而提升开发效率和代码质量。


更多关于Flutter扩展功能插件dartx的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter扩展功能插件dartx的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用dartx扩展功能插件的示例。dartx是一个提供了一系列实用扩展函数的Dart库,它可以帮助你以更简洁和高效的方式编写Flutter代码。

1. 添加依赖

首先,你需要在你的pubspec.yaml文件中添加dartx的依赖:

dependencies:
  flutter:
    sdk: flutter
  dartx: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get来安装依赖。

2. 导入库

在你的Dart文件中导入dartx库:

import 'package:dartx/dartx.dart';

3. 使用扩展函数

dartx提供了许多实用的扩展函数,以下是一些常见用法的示例:

字符串操作

void main() {
  String str = "Hello, Flutter!";
  
  // 使用dartx的isEmptyOrWhitespace扩展函数检查字符串是否为空或仅包含空白字符
  bool isEmptyOrWhitespace = str.isEmptyOrWhitespace();
  print("Is empty or whitespace: $isEmptyOrWhitespace");  // 输出: false
  
  // 使用dartx的capitalize扩展函数将字符串首字母大写
  String capitalizedStr = str.capitalize();
  print("Capitalized: $capitalizedStr");  // 输出: Hello, Flutter!
}

集合操作

void main() {
  List<int> numbers = [1, 2, 3, 4, 5];
  
  // 使用dartx的chunkBySize扩展函数将集合按指定大小分块
  List<List<int>> chunkedNumbers = numbers.chunkBySize(2);
  print("Chunked: $chunkedNumbers");  // 输出: [[1, 2], [3, 4], [5]]
  
  // 使用dartx的containsAll扩展函数检查集合是否包含另一个集合的所有元素
  List<int> subset = [1, 2];
  bool containsAll = numbers.containsAll(subset);
  print("Contains all: $containsAll");  // 输出: true
}

日期和时间操作

void main() {
  DateTime now = DateTime.now();
  
  // 使用dartx的startOfDay扩展函数获取当前日期的开始时间(00:00:00)
  DateTime startOfDay = now.startOfDay();
  print("Start of day: $startOfDay");
  
  // 使用dartx的isWeekend扩展函数检查日期是否是周末
  bool isWeekend = now.isWeekend();
  print("Is weekend: $isWeekend");  // 根据当前日期输出 true 或 false
}

4. 完整示例

以下是一个完整的Flutter应用示例,展示了如何使用dartx进行字符串、集合和日期时间的操作:

import 'package:flutter/material.dart';
import 'package:dartx/dartx.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Dartx Example'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('String Operations:'),
              Text('Is empty or whitespace: ${"Hello".isEmptyOrWhitespace()}'),
              Text('Capitalized: ${"hello".capitalize()}'),
              
              SizedBox(height: 20),
              
              Text('List Operations:'),
              Text('Chunked: ${[1, 2, 3, 4, 5].chunkBySize(2).map((e) => e.join(', ')).join(', ')}'),
              Text('Contains all: ${[1, 2, 3, 4, 5].containsAll([1, 2])}'),
              
              SizedBox(height: 20),
              
              Text('DateTime Operations:'),
              Text('Start of day: ${DateTime.now().startOfDay().toLocal()}'),
              Text('Is weekend: ${DateTime.now().isWeekend()}'),
            ],
          ),
        ),
      ),
    );
  }
}

以上代码展示了如何在Flutter应用中使用dartx库提供的扩展函数来简化字符串、集合和日期时间的操作。希望这些示例能帮助你更好地理解和使用dartx

回到顶部