Flutter扩展工具插件extension_utils的使用

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

Flutter扩展工具插件extension_utils的使用

extension_utils 是一个实用库,提供了对字符串、列表、映射等类型的各种扩展方法。本文将详细介绍该插件的功能和使用方法,并提供完整的示例代码。

功能特性

  • ✅ 字符串扩展
  • ✅ 列表扩展
  • ✅ 映射扩展
  • ✅ 日期时间扩展
  • ✅ 数字扩展
  • ✅ 枚举扩展
  • ❌ 颜色扩展(即将添加)

安装

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

dependencies:
  extension_utils: ^1.0.1

然后运行 flutter pub get 来安装插件。

使用示例

字符串扩展

import 'package:extension_utils/extension_utils.dart';

void main() {
  print('Hello, World!'.toSnakeCase()); // hello_world
}

更多字符串扩展示例:

print('hello, world!'.capitalize()); // Hello, world!
print('Hello, World!'.uncapitalize()); // hello, World!
print('hello, world!'.titleCase()); // Hello, World!
print('hello, world!'.underscore()); // hello_world
print('hello, world!'.variablize()); // helloWorld
print('hello, world!'.constantize()); // HELLO_WORLD
print('hello, world!'.humanize()); // Hello world
print('hello, world!'.pluralize()); // hello, worlds!
print('hello, world!'.tableize()); // hello_worlds
print('hello, world!'.sequenceize()); // hello_worlds
print('hello, world!'.foreignKey()); // hello_world_id
print('hello, world!'.pathize()); // hello/world
print('hello, world!'.toPascalCase()); // HelloWorld
print('hello, world!'.toSnakeCase()); // hello_world
print('hello, world!'.toKebabCase()); // hello-world
print('hello, world!'.toTrainCase()); // Hello-World
print('hello, world!'.toDotCase()); // hello.world
print('hello, world!'.toHtmlText()); // hello, world!
print('hello,\wworld!'.escape()); // hello,\\wworld!
print('dad'.isPalindrome()); // true
print('email@gmail.com'.isEmail()); // true
print('983123'.isDigits()); // true
print('#FFFFFF'.isHexColor()); // true
print('#FFFFFF'.toColor()); // Color(0xffffffff)
print('hello, world!'.wordCount()); // 2
print('hello, world!'.charCount()); // 13
print('hello, world!'.vowelCount()); // 3
print('hello, world!'.consonantCount()); // 8
print('hello, world!'.syllableCount()); // 3
print('hello, world!'.sentenceCount()); // 1
print('hello, world!'.between('hello', '!')); // , world
print('hello, world!'.before('world')); // hello, 
print('hello, world!'.after('hello')); // , world!
print('hello, world!'.beforeLast('o')); // hello, w
print('hello, world!'.afterLast('o')); // rld!
print('hello, world!'.beforeFirst('o')); // hell
print('hello, world!'.afterFirst('o')); // , world!
print('hello, world!'.startsWith('hello')); // true
print('hello, world!'.endsWith('!')); // true
print('hello, world!'.betweenFirst('hello', '!')); // , world
print('hello, world!'.betweenLast('hello', '!')); // , world
print('hello, world!'.containsIgnoreCase('HELLO')); // true
print('hello, world!'.dropLeft(6)); // world!
print('hello, world!'.dropRight(6)); //  hello,
print('hello, world!'.dropLeftWhile((c) => c != ' ')); // world!
print('hello, world!'.dropRightWhile((c) => c != ' ')); // hello,
print('hello, world!'.replaceAfterFirst('hello', '!')); // hello!
print('hello, world!'.replaceAfterLast('hello', '!')); // hello!
print('hello, world!'.replaceBeforeFirst('hello', '!')); // !, world!
print('hello, world!'.replaceBeforeLast('hello', '!')); // !, world!
print('hello, world!'.replaceRange(0, 5, 'hi')); // hi, world!
print('hello, world!'.toBytes()); // [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33]
print('hello, world!'.toBase64()); // aGVsbG8sIHdvcmxkIQ==
print('hello, world!'.prepend('hi, ')); // hi, hello, world!
print('hello, world!'.append('!')); // hello, world!!
print('hello, {}!'.format(['world'])); // hello, world!
print('hello, {name}!'.formatMap({'name': 'world'})); // hello, world!

列表扩展

['hello', 'world'].removeFirst(); // ['world']
['hello', 'world'].removeLast(); // ['hello']
['hello','world','hello','world'].removeAll('hello'); // ['world','world']
['lorem','ipsum','hello', 'world'].removeAllList(['lorem','hello']); // ['ipsum','world']
['lorem','ipsum','hello', 'world'].removeAllSet({'lorem','hello'}); // ['ipsum','world']
['lorem','ipsum','hello', 'world'].removeAllIterable(['lorem','hello']); // ['ipsum','world']
['lorem','ipsum','hello', 'world'].removeAllMapKeys({'lorem': 'ipsum', 'hello': 'world'}); // ['ipsum','world']
['lorem','ipsum','hello', 'world'].removeAllMapValues({'lorem': 'ipsum', 'hello': 'world'}); // ['lorem','hello']
['hi','hello','lorem', 'ipsum'].parititon((s) => s.startsWith('h')); // Pair(['hi','hello'],['lorem', 'ipsum'])
[Product(qty: 5, price: 10), Product(qty: 10, price: 20)].sumBy((p) => p.qty * p.price); // 250
['lorem','ipsum','hello', 'world'].containsAllList(['lorem','hello']); // true
['lorem','ipsum','hello', 'world'].containsAllSet({'lorem','hello'}); // true
['lorem','ipsum','hello', 'world'].containsAllIterable(['lorem','hello']); // true
['lorem','ipsum','hello', 'world'].containsAllMapKeys({'lorem': 'ipsum', 'hello': 'world'}); // true
['lorem','ipsum','hello', 'world'].containsAllMapValues({'lorem': 'ipsum', 'hello': 'world'}); // false
['lorem','ipsum','hello', 'world'].mergeList(['lorem','hello'],unique: true); // ['lorem','ipsum','hello', 'world','lorem']
['lorem','ipsum','hello', 'world'].toMap(); // {'lorem': 'lorem','ipsum': 'ipsum','hello': 'hello', 'world': 'world'}
['lorem','ipsum','helloo', 'world'].distinctBy((a) => a.length == 5); // ['lorem','helloo']
['lorem','ipsum','hello', 'world'].compact(); // ['lorem','ipsum','hello', 'world']
['lorem','ipsum','hello', 'world'].clearAndAddAll(['lorem','hello']); // ['lorem','hello']
['hi', 'ipsum', 'hello', 'bro'].sortedBy((s) => s.length); // ['hi', 'bro', 'hello', 'ipsum']
['hi', 'ipsum', 'hello', 'bro'].sortByDescending((s) => s.length); // ['ipsum', 'hello', 'hi', 'bro']
['hi', 'ipsum', 'hello', 'bro'].groupBy((s) => s.length); // {2: ['hi', 'bro'], 5: ['ipsum', 'hello']}
['hi', 'ipsum', 'hello', 'bro'].joinToString(','); // hi,ipsum,hello,bro
['hi', 'ipsum', 'hello', 'bro'].joinToString(',', transform: (s) => s.toUpperCase()); // HI,IPSUM,HELLO,BRO
['hi', 'ipsum', 'hello', 'bro'].joinToString(',', prefix: '(', suffix: ')'); // (hi,ipsum,hello,bro)
[1,2,3,4,5,6].takeWhile((i) => i < 4); // [1,2,3]
[1,2,3,4,5,6].takeIf((i) => i < 4 || i == 5 ); // [1,2,3,5]

数字扩展

print(1.0.isEven()); // false
print(1.0.isOdd()); // true
print(1.0.isNegative()); // false
print(1.0.isPositive()); // true
print(1.0.isZero()); // false
print((1/2).isInteger()); // false
print(-2.swapSign()); // 2
print(2.swapSign()); // -2
print(2.000524.toPrecision(3)); // 2.00
print(2.000524.toPrecision(4)); // 2.001
print(645123512.toCurrencyString()); // 645,123,512.00
print(2.000524.isInRange(1, 3)); // true
print(9842323112.startsWith(984)); // true
print(9842323112.endsWith(112)); // true
print(9842323112.contains(232)); // true
print(9842323112.count(2)); // 3
print(12312412.indexesOfFirst(2)); // 1
print(12312412.indexesOfLast(2)); // 5
print(12312412.indexesOfAll(2)); // [1, 5]
print(9876543210.sumOfDigits()); // 45
print(9876543210.digitsAfter(2)); // 10
print(9876543210.digitsBefore(2)); // 98765432
print(9876543210.digitsBetween(9, 4)); // 8765
print(9872543210.digitsBeforeFirst(2)); // 987
print(9872543210.digitsAfterFirst(2)); // 543210
print(9872543210.digitsBeforeLast(2)); // 9872543
print(9872543210.digitsAfterLast(2)); // 10
print(10.loremIpsum()); // Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
print(20.randomList(min: 1, max: 10)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

映射扩展

print({}.isEmpty()); // true
print({'hello': 'world'}.contains('hello','world')); // true
print({'hello': 'world','lorem': 'ipsum'}.removeExact(key: 'hello', value: 'world')); // {'lorem': 'ipsum'}
print({'hello': 'world','lorem': 'ipsum'}.prefixKeys('product-')) // {'product-hello': 'world','product-lorem': 'ipsum'}
print({'hello': 'world','lorem': 'ipsum'}.suffixKeys('-product')) // {'hello-product': 'world','lorem-product': 'ipsum'}
print({'hello': 'world','lorem': 'ipsum'}.prefixValues('product-')) // {'hello': 'product-world','lorem': 'product-ipsum'}
print({'hello': 'world','lorem': 'ipsum'}.suffixValues('-product')) // {'hello': 'world-product','lorem': 'ipsum-product'}
print({'hello': 'world','lorem': 'ipsum'}.capitalizeKeys()) // {'Hello': 'world','Lorem': 'ipsum'}
print({'hello': 'world','lorem': 'ipsum'}.capitalizeValues()) // {'hello': 'World','lorem': 'Ipsum'}
print({'hello world': 'lorem ipsum'}.camelCaseKeys()) // {'helloWorld': 'lorem ipsum'}
print({'hello world': 'lorem ipsum'}.camelCaseValues()) // {'hello world': 'loremIpsum'}
print({'hello world': 'lorem ipsum'}.snakeCaseKeys()) // {'hello_world': 'lorem ipsum'}
print({'hello world': 'lorem ipsum'}.snakeCaseValues()) // {'hello world': 'lorem_ipsum'}
print({'hello world': 'lorem ipsum'}.kebabCaseKeys()) // {'hello-world': 'lorem ipsum'}
print({'hello world': 'lorem ipsum'}.kebabCaseValues()) // {'hello world': 'lorem-ipsum'}
print({'hello': 'world','lorem': 'ipsum','hi': 'there'}.partition((key, value) => key.length == 5)); // [{'hello': 'world', 'lorem': 'ipsum'},{'hi': 'there'}]
print({'hello': 'world','lorem': 'ipsum'}.filter((key, value) => key == 'hello')) // {'hello': 'world'}
print({'hello': 'world','lorem': 'ipsum'}.filterNull()) // {'hello': 'world','lorem': 'ipsum'}
print({'hello': 'world','lorem': 'ipsum'}.filterEmpty()) // {'hello': 'world','lorem': 'ipsum'}
print({'hello': 'world','lorem': 'ipsum'}.filterKeys(['hello'])) // {'hello': 'world'}
print({'hello': 'world','lorem': 'ipsum'}.filterValues(['world'])) // {'hello': 'world'}
print({'hello': 'world','lorem': 'ipsum'}.filterNot((key, value) => key == 'hello')) // {'lorem': 'ipsum'}
print({'hello': 'world','lorem': 'ipsum'}.reject((key, value) => key == 'hello')) // {'lorem': 'ipsum'}
print({'hello': 'world','lorem': 'ipsum'}.rejectKeys(['hello'])) // {'lorem': 'ipsum'}
print({'hello': 'world,lorem': 'ipsum'}.rejectValues(['world'])) // {'lorem': 'ipsum'}
print({'hello': 'world','lorem': 'ipsum'}.rejectNot((key, value) => key == 'hello')) // {'hello': 'world'}
print({'hello': 'world','lorem': 'ipsum'}.shift()) // {'lorem': 'ipsum'}
print({'hello': 'world','lorem': 'ipsum'}.printDebug(label: 'Map', separator: ': ', indent: ',  ')) // Map: hello: world,  lorem: ipsum
print({'hello': 'world','lorem': 'ipsum','lo': 'ipsum'}.uniqueValues()) // {'hello': 'world','lorem': 'ipsum'}

日期时间扩展

print(DateTime.now().isToday()); // true
print(DateTime.now().isYesterday()); // false
print(DateTime.now().isTomorrow()); // false
print(DateTime.now().isPast()); // false
print(DateTime.now().isFuture()); // false
print(DateTime.now().isSameDay(DateTime.now())); // true
print(DateTime.now().isSameMonth(DateTime.now())); // true
print(DateTime.now().isSameYear(DateTime.now())); // true
print(DateTime.now().isSameHour(DateTime.now())); // true
print(DateTime.now().isSameMinute(DateTime.now())); // true
print(DateTime.now().isSameSecond(DateTime.now())); // true
print(DateTime.now().isSameMillisecond(DateTime.now())); // true
print(DateTime.now().isAheadByDays(DateTime.now(), 1)); // false
print(DateTime.now().isBehindByDays(DateTime.now(), 1)); // false
print(DateTime.now().isMorning()); // true
print(DateTime.now().isAfternoon()); // false
print(DateTime.now().isEvening()); // false
print(DateTime.now().isNight()); // false
print(DateTime.now().isWeekend()); // false
print(DateTime.now().isWeekday()); // true
print(DateTime.now().isHoliday()); // false
print(DateTime.now().daysUntil(DateTime.now())); // 0
print(DateTime.now().hoursUntil(DateTime.now())); // 0
print(DateTime.now().daysUntilEndOfYear()); // 0
print(DateTime.now().season()); // 'winter'
print(DateTime.now().isInSeason('winter')); // true
print(DateTime.now().isLeapYear()); // false
print(DateTime.now().daysUntilWeekend()); // 5

枚举扩展

enum UserType { admin, user, guest }

UserType userType = UserType.admin;

userType.when({
  UserType.admin: () => debugPrint('Admin'),
  UserType.user: () => debugPrint('User'),
  UserType.guest: () => debugPrint('Guest'),
}); // 'Admin'

userType.whenOrElse({
  UserType.admin: () => debugPrint('Admin'),
  UserType.user: () => debugPrint('User'),
}, orElse: () => debugPrint('Guest')); // 'Admin'

示例应用

以下是完整的示例应用代码:

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Extension Utils Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Extension Utils Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  UserType user = UserType.admin;

  [@override](/user/override)
  void initState() {
    super.initState();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    user.when({
      UserType.admin: () => debugPrint('Admin'),
      UserType.user: () => debugPrint('User'),
      UserType.guest: () => debugPrint('Guest')
    });

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('String Example: ${'Hello, World!'.toSnakeCase()}'),
            Text('List Example: ${['hello', 'world'].removeFirst()}'),
            Text('Number Example: ${1.0.isOdd()}'),
            Text('DateTime Example: ${DateTime.now().isToday()}'),
          ],
        ),
      ),
    );
  }
}

enum UserType {
  admin,
  user,
  guest,
}

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

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用extension_utils扩展工具插件的示例代码。这个示例将展示如何创建一个简单的Flutter插件,并使用extension_utils来注册和调用一些原生方法。

1. 设置Flutter项目

首先,确保你已经有一个Flutter项目。如果没有,可以通过以下命令创建一个新的Flutter项目:

flutter create my_flutter_app
cd my_flutter_app

2. 添加extension_utils依赖

在你的pubspec.yaml文件中添加extension_utils依赖(注意:如果extension_utils是一个实际存在的包,你应该在pub.dev上找到它并添加正确的依赖。如果这是一个假设的包名,你需要替换为实际的插件):

dependencies:
  flutter:
    sdk: flutter
  extension_utils: ^x.y.z  # 替换为实际的版本号

然后运行flutter pub get来获取依赖。

3. 创建原生平台通道

iOS平台

ios/Runner目录下,打开AppDelegate.swift(如果是Objective-C项目,则是AppDelegate.m),并添加以下代码来注册方法:

import UIKit
import Flutter
import extension_utils  // 假设extension_utils在iOS上有对应的桥接

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    
    // 注册自定义方法
    let channel = FlutterMethodChannel(name: "com.example.my_flutter_app/channel", binaryMessenger: self.registrar(forPlugin: "extension_utils")?.messenger())
    channel.setMethodCallHandler {
      (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
      
      switch call.method {
      case "someNativeMethod":
        let message = call.arguments as! String
        let response = "Hello from iOS: \(message)"
        result(response)
      default:
        result(FlutterMethodNotImplemented)
      }
    }
    
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

Android平台

android/app/src/main/java/com/example/my_flutter_app/MainActivity.kt(如果是Java项目,则是MainActivity.java),添加以下代码来注册方法:

package com.example.my_flutter_app

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import extension_utils.MyNativeMethods  // 假设extension_utils在Android上有对应的类

class MainActivity: FlutterActivity() {
    private val CHANNEL = "com.example.my_flutter_app/channel"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
            call, result ->
            if (call.method == "someNativeMethod") {
                val message = call.argument<String>("message") ?: ""
                val response = "Hello from Android: $message"
                result.success(response)
            } else {
                result.notImplemented()
            }
        }
    }
}

4. 在Dart代码中调用原生方法

打开lib/main.dart,并添加以下代码来调用原生方法:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:extension_utils/extension_utils.dart';  // 假设extension_utils提供了Dart接口

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

class MyApp extends StatelessWidget {
  static const platform = MethodChannel('com.example.my_flutter_app/channel');

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: _invokeNativeFunction,
            child: Text('Invoke Native Function'),
          ),
        ),
      ),
    );
  }

  Future<void> _invokeNativeFunction() async {
    try {
      final String result = await platform.invokeMethod('someNativeMethod', "Hello from Dart");
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text("Native response: $result")),
      );
    } on PlatformException catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text("Failed to invoke: '${e.message}'")),
      );
    }
  }
}

总结

以上代码展示了如何在Flutter项目中集成和使用一个名为extension_utils的插件(假设它存在)。这包括在Dart代码中调用原生方法,以及在iOS和Android平台上注册和实现这些方法。

请注意,extension_utils是一个假设的包名,实际使用时你需要替换为具体的插件名和正确的依赖。如果extension_utils不是一个实际存在的包,你可能需要找到一个类似的插件或自己创建一个原生插件来实现所需的功能。

回到顶部