Flutter自定义命令执行插件prop_commands的使用
Flutter自定义命令执行插件prop_commands的使用
该插件包含以下装饰类:Property<T>、Command、ParameterizedCommand<T>、AsyncCommand、ParameterizedAsyncCommand<T>。这些类在基于 ChangeNotifier 的视图模型创建时非常有用。
示例 #1
 
属性和命令在视图模型类 FirstPageNotifier 中定义。
属性
用于存储计数器值
late final outputProperty = Property<int>(
    initialValue: 0,
    notifyListeners: notifyListeners,
);
属性的初始值设置,并且当此属性的值发生变化时调用 notifyListeners() 方法。
在 FirstPage 类的 build(BuildContext context) 方法中,我们获取对属性值的跟踪引用
final output =
    FirstPageInheritedNotifier.watchNotifier(context).outputProperty.value;
输出值的方式如下
Text(
    output.toString(),
    style: Theme.of(context).textTheme.headlineLarge,
),
命令
为计数器的递增和递减创建了两个命令
late final incrementCommand = Command(
    action: () => outputProperty.value += 1,
    canAction: () => outputProperty.value < 3,
);
late final decrementCommand = Command(
    action: () => outputProperty.value -= 1,
    canAction: () => outputProperty.value > 0,
);
传递更改计数器属性值的方法作为 action 参数的参数。传递限制计数器值范围的方法作为 canAction 参数的参数,这限制了命令的可用性。
在 FirstPage 类的 build(BuildContext context) 方法中获取到命令的引用
final incrementCommand =
    FirstPageInheritedNotifier.readNotifier(context).incrementCommand;
final decrementCommand =
    FirstPageInheritedNotifier.readNotifier(context).decrementCommand;
使用命令来操作按钮
ElevatedButton(
    onPressed: decrementCommand.canExecute()
        ? decrementCommand.execute
        : null,
    child: const Icon(Icons.exposure_minus_1),
),
和
ElevatedButton(
    onPressed: incrementCommand.canExecute()
        ? incrementCommand.execute
        : null,
    child: const Icon(Icons.plus_one),
),
可以看到,在 onPressed 方法中检查了命令的可执行性,这影响了按钮的点击可用性。
示例 #2
 
属性和命令在视图模型类 SecondPageNotifier 中定义。
属性
定义一个属性以显示计数器值,该属性仅通过其初始值设置。
final outputProperty = Property<int>(initialValue: 0);
在 SecondPage 类的 build(BuildContext context) 方法中获取对属性值的跟踪引用
final output =
    SecondPageInheritedNotifier.watchNotifier(context).outputProperty.value;
显示属性值的方式如下
Text(
    output.toString(),
    style: Theme.of(context).textTheme.headlineLarge,
),
命令
定义了一个通用的参数化命令,用于按钮,
当调用执行时,将接受一个 int 值作为参数。
late final changeCommand = ParameterizedCommand<int>(
    action: (value) => outputProperty.value += value,
    notifyListeners: notifyListeners,
);
在执行命令方法时,调用 notifyListeners()。
在 SecondPage 类的 build(BuildContext context) 方法中我们获取到命令的引用
final command =
        SecondPageInheritedNotifier.readNotifier(context).changeCommand;
使用命令的方式如下
ElevatedButton(
    onPressed: () => command(-1),
    child: Text(
        '-1',
        style: Theme.of(context).textTheme.titleLarge,
    ),
),
...
ElevatedButton(
    onPressed: () => command(3),
    child: Text(
        '3',
        style: Theme.of(context).textTheme.titleLarge,
    ),
),
示例 #3
 
在视图模型类 ThirdPageNotifier 中定义了三个属性和一个命令。
属性
设置了带有 notifyListeners() 调用的 CheckboxListTile 属性。
late final isEnabledProperty = Property<bool>(
    initialValue: false,
    notifyListeners: notifyListeners,
);
接下来,在 _ThirdPageState 中获取到这个属性的跟踪引用
final isEnabledProperty =
    ThirdPageInheritedNotifier.watchNotifier(context).isEnabledProperty;
并这样使用它
CheckboxListTile(
    title: const Text('启用输入行'),
    controlAffinity: ListTileControlAffinity.platform,
    contentPadding: const EdgeInsets.all(50),
    value: isEnabledProperty.value,
    onChanged: (value) {
        isEnabledProperty.value = value!;
    },
),
设置了带有 notifyListeners() 调用和验证规则的 TextField 属性。
late final inputProperty = Property<String>(
    initialValue: '',
    notifyListeners: notifyListeners,
    verificationRules: <String, bool Function(String)>{
      '值不能为空字符串': (value) => value.isEmpty,
      '字符串长度不能少于3个字符': (value) => value.length < 3,
    },
);
对于验证规则,指定用户文本消息作为键,返回 true 的方法作为值。
在 InputTextWidget 中获取到属性的引用
final isEnabledProperty =
        ThirdPageInheritedNotifier.watchNotifier(context).isEnabledProperty;
final inputProperty =
    ThirdPageInheritedNotifier.readNotifier(context).inputProperty;
并这样使用它
TextField(
    decoration: InputDecoration(
        border: const OutlineInputBorder(),
        labelText: '输入值',
        errorText: inputProperty.hasErrors ? inputProperty.errors[0] : null,
    ),
    enabled: isEnabledProperty.value,
    controller: controller,
    onChanged: (text) {
        inputProperty.value = text;
    },
),
在这一行 errorText: inputProperty.hasErrors ? inputProperty.errors[0] : null, 定义了当输入数据时向用户显示错误消息的逻辑。
通过 isEnabledProperty 属性将 TextField 的输入可用性与 CheckboxListTile 的值绑定在一起
enabled: isEnabledProperty.value,
inputProperty 属性在 onChanged 方法中定义的更新其值。
简单的属性用于输出结果
final outputProperty = Property<String>(initialValue: '');
命令
该示例使用了一个异步命令
late final submitCommand = AsyncCommand(
    action: () async {
      await Future.delayed(const Duration(milliseconds: 100));
      outputProperty.value = inputProperty.value;
      inputProperty.value = '';
      isEnabledProperty.value = false;
    },
    canAction: () => inputProperty.hasErrors == false,
    notifyListeners: notifyListeners,
);
按钮的可用性取决于输入时是否存在错误
canAction: () => inputProperty.hasErrors == false,
在执行命令方法时,调用 notifyListeners()。
在 _ThirdPageState 中获取到命令的引用
final submitCommand =
    ThirdPageInheritedNotifier.readNotifier(context).submitCommand;
并这样使用命令
ElevatedButton(
    onPressed: submitCommand.canExecute()
        ? (() async {
            await submitCommand.execute();
            controller.clear();
        })
        : null,
    child: const Icon(Icons.done),
),
示例 #4
 
在 FourthPageNotifier 视图模型类中定义了一个属性和三个命令。
属性
创建了一个属性以显示列表。
final peopleProperty = Property<List<Person>>(
    initialValue: [],
);
在 PeopleListViewWidget 中获取到属性的跟踪引用
final people =
    FourthPageInheritedNotifier.watchNotifier(context).peopleProperty.value;
使用 ListView.builder() 和 ListTile 显示人员集合
ListView.builder(
    itemCount: people.length,
    itemBuilder: (context, index) {
        final person = people[index];
        return ListTile(
            onTap: () async {...},
            title: Text(person.fullName),
            subtitle: Text('ID: ${person.id}'),
            trailing: TextButton(...),
        );
    },
),
命令
为了实现对人员集合的CRUD操作,创建了三个参数化的异步命令:addCommand、removeCommand、updateCommand。
以 addCommand 为例。
late final addCommand = ParameterizedAsyncCommand<List<String>>(
    action: (value) async {
      await _db.create(names: value);
      peopleProperty.value = await _db.getPeople();
    },
    notifyListeners: notifyListeners,
);
在 Composerwidget 中的 Widget build(BuildContext context) 方法中获取到命令的引用
final command =
    FourthPageInheritedNotifier.readNotifier(context).addCommand;
我们这样使用命令
TextButton(
    onPressed: () async {
        final names = [
            firstNameController.text,
            lastNameController.text,
        ];
        await command(names);
        firstNameController.clear();
        lastNameController.clear();
    },
    child: Text(
    '添加到列表',
    style: Theme.of(context).textTheme.titleMedium,
))
更多关于Flutter自定义命令执行插件prop_commands的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter自定义命令执行插件prop_commands的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在 Flutter 中,你可以通过创建自定义插件来执行特定的命令或功能。prop_commands 并不是 Flutter 官方提供的插件,因此它可能是某个开发者或团队创建的自定义插件。为了帮助你理解如何使用自定义命令执行插件,我将提供一个通用的步骤和示例,假设你有一个名为 prop_commands 的插件。
1. 添加插件依赖
首先,你需要在 pubspec.yaml 文件中添加插件的依赖。假设 prop_commands 已经发布在 pub.dev 上,你可以这样添加依赖:
dependencies:
  flutter:
    sdk: flutter
  prop_commands: ^1.0.0  # 假设插件的版本是 1.0.0
然后运行 flutter pub get 来获取依赖。
2. 导入插件
在你的 Dart 文件中导入插件:
import 'package:prop_commands/prop_commands.dart';
3. 使用插件执行命令
假设 prop_commands 插件提供了一个 executeCommand 方法来执行命令,你可以这样使用它:
void executeCustomCommand() async {
  try {
    String result = await PropCommands.executeCommand('your_command_here');
    print('Command executed successfully: $result');
  } catch (e) {
    print('Failed to execute command: $e');
  }
}
4. 处理命令结果
executeCommand 方法可能会返回一个 String 或其他类型的结果,你可以根据需要进行处理。例如,将结果显示在 UI 上:
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Prop Commands Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              String result = await PropCommands.executeCommand('your_command_here');
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('Result: $result')),
              );
            },
            child: Text('Execute Command'),
          ),
        ),
      ),
    );
  }
}
5. 处理错误
在执行命令时,可能会遇到错误。你可以使用 try-catch 块来捕获并处理这些错误。
6. 自定义插件的实现
如果你需要自己实现一个类似的插件,你可以使用 Flutter 的 MethodChannel 来与平台(Android/iOS)进行通信。以下是一个简单的示例:
Dart 部分 (lib/prop_commands.dart):
import 'package:flutter/services.dart';
class PropCommands {
  static const MethodChannel _channel = MethodChannel('prop_commands');
  static Future<String> executeCommand(String command) async {
    try {
      final String result = await _channel.invokeMethod('executeCommand', {'command': command});
      return result;
    } on PlatformException catch (e) {
      throw 'Failed to execute command: ${e.message}';
    }
  }
}
Android 部分 (android/src/main/kotlin/com/example/prop_commands/PropCommandsPlugin.kt):
package com.example.prop_commands
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar
class PropCommandsPlugin: MethodCallHandler {
  companion object {
    @JvmStatic
    fun registerWith(registrar: Registrar) {
      val channel = MethodChannel(registrar.messenger(), "prop_commands")
      channel.setMethodCallHandler(PropCommandsPlugin())
    }
  }
  override fun onMethodCall(call: MethodCall, result: Result) {
    when (call.method) {
      "executeCommand" -> {
        val command = call.argument<String>("command")
        // 执行命令并返回结果
        result.success("Executed: $command")
      }
      else -> result.notImplemented()
    }
  }
}
iOS 部分 (ios/Classes/PropCommandsPlugin.m):
#import "PropCommandsPlugin.h"
[@implementation](/user/implementation) PropCommandsPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
  FlutterMethodChannel* channel = [FlutterMethodChannel
      methodChannelWithName:@"prop_commands"
            binaryMessenger:[registrar messenger]];
  PropCommandsPlugin* instance = [[PropCommandsPlugin alloc] init];
  [registrar addMethodCallDelegate:instance channel:channel];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
  if ([@"executeCommand" isEqualToString:call.method]) {
    NSString *command = call.arguments[@"command"];
    // 执行命令并返回结果
    result([NSString stringWithFormat:@"Executed: %@", command]);
  } else {
    result(FlutterMethodNotImplemented);
  }
}
[@end](/user/end)
7. 注册插件
在 android/app/src/main/kotlin/com/example/your_app/MainActivity.kt 和 ios/Runner/AppDelegate.swift 中注册插件。
Android:
import com.example.prop_commands.PropCommandsPlugin
class MainActivity: FlutterActivity() {
  override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    PropCommandsPlugin.registerWith(registrarFor("com.example.prop_commands.PropCommandsPlugin"))
  }
}
iOS:
#import "GeneratedPluginRegistrant.h"
#import "PropCommandsPlugin.h"
[@implementation](/user/implementation) AppDelegate
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  [PropCommandsPlugin registerWithRegistrar:[self registrarForPlugin:@"PropCommandsPlugin"]];
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
[@end](/user/end) 
        
       
             
             
            

