Flutter原生模块集成插件swift_composer的使用

Flutter原生模块集成插件swift_composer的使用

警告: 该模块处于实验阶段,正在开发中。其API可能会发生变化。

Swift Composer旨在将Dart模块转换为可插拔的应用程序部分。它使用source_gen生成最终的应用逻辑,依赖于导入的模块和配置,因此不会生成多余的样板代码。该模块支持用于生成可插拔的客户端和服务器端路由、自动序列化的数据模型、可配置的布局和小部件系统等。

安装

  1. pubspec.yaml文件中添加swift_composer到你的依赖项:
dependencies:
  swift_composer: any
  1. 在你的最终应用程序代码中声明一个编译的部分:
import 'package:swift_composer/swift_composer.dart';

import 'package:some_plugin';

part 'main.c.dart';

void main() {
  $om.some_compiled_entrypoint.run();
}
  1. 构建.c.dart部分
pub run build_runner build

如果你正在创建一个Web包,构建将会自动执行,使用webdev serve/build

特性

要求

任何要使用Swift Composer功能的类都需要被声明为抽象类,并且用@Compose注解装饰。这允许代码生成器生成带有编译方法、插件和依赖注入的最终类。

@Compose
abstract class Foo {

}
类名
@Compose
abstract class Foo {

  @InjectClassName
  String get className;

  @InjectClassNames
  List<String> get classNames;

}

所有Test及其子类型的实例将在编译后具有className字段,其中包含类的全名,classNames字段包含类层次结构路径。这对于序列化非常有用,因为即使在编译到*.js等格式之后,此字段仍会保留源类名。

依赖注入
@Compose
abstract class Bar {

  @Require
  String barRequiredField;

}

@Compose
abstract class Test {

  @Inject
  Foo get injectedFoo;

  @Factory
  Foo createFoo();

  @Factory
  Bar createBar(String barRequiredField);

}

Factory装饰的方法将创建返回类型的编译子类型。返回的确切类型由导入的模块和DI配置定义。对于没有创建所需依赖项的类,可以使用Inject注解来生成共享实例。

查找类子类型
@Compose
abstract class Test {

@InjectInstances
Map<String, Foo> get instances;

@SubtypeFactory
Foo createFoo(String className);

}

SubtypeFactory装饰的方法将根据传递的className参数返回Foo的子类型。用InjectInstances装饰的getter将包含一个映射,键为Foo的所有无依赖项子类型的类名。

类字段信息和编译方法

Swift Composer提供了生成最终类字段信息的工具,可用于例如生成JSON序列化。

const JsonField = true;

@Compose
abstract class TestSerializable {

  @InjectClassName
  String get className;

  @JsonField
  String foo;

  @JsonField
  String bar;

  Map toJson() {
      Map ret = new Map();
      ret['className'] = className;
      this.fieldsToJson(ret);
      return ret;
  }

  @Compile
  void fieldsToJson(Map target);

  @CompileFieldsOfType
  @AnnotatedWith(JsonField)
  void _fieldsToJsonString(Map target, String name, String field) {
    target[name] = field;
  }

  @CompileFieldsOfType
  @AnnotatedWith(JsonField)
  void _fieldsToJsonInt(Map target, String name, int field) {
    target[name] = field;
  }

}

在上面的例子中,所有TestSerializable的子类型都将有一个toJson方法,该方法将序列化带有@JsonField注解的所有字段。

类型插件

类型插件可以修改对象的数据和行为。字段编译方法与插件一起工作,也会编译插件字段,因此我们可以为前面的TestSerializable示例添加一个插件。

abstract class TestPlugin extends TypePlugin<TestSerializable> {

  @Field
  String extraField = 'test';

}

现在,调用toJson应该返回类似以下内容:

{
  'className' : 'TestSerializable',
  'foo' : 'something',
  'bar' : 10,
  'testPlugin.extraField': 'test'
}

我们还可以使用MethodPlugin注解扩展/更改装饰类的行为。

父类中的每个公共方法:

  bool validate(int foo, int bar) {
    return foo > bar;
  }

插件类可以自定义此类方法的行为:

  @MethodPlugin
  List<dynamic> beforeValidate(int foo, int bar) {
    bar = bar + 1;
    return [foo, bar];
  }

  @MethodPlugin
  bool afterValidate(bool ret) {
    return !ret;
  }

开发信息

运行测试:

dart run build_runner build && dart test/swift_composer_test.dart

完整示例

下面是一个完整的示例,演示了如何使用swift_composer插件。

import 'package:swift_composer/swift_composer.dart';
import 'module_fruits.dart' as module_fruit;
import 'module_banana.dart' as module_banana;
import 'module_price.dart' as module_price;
import 'module_discount.dart' as module_discount;

part 'main.c.dart';

void main() {

  List<module_fruit.Fruit> fruits = [];

  fruits.addAll([
    $om.module_fruit_AllAvailableFruits.createFruit('module_fruit.Fruit', "Fruit 1"),
    $om.module_fruit_AllAvailableFruits.createFruit('module_fruit.Fruit', "Fruit 2")
      ..width = 50
      ..height = 10,
    $om.module_fruit_AllAvailableFruits.createFruit('module_banana.Banana', "Banana 1"),
    $om.module_fruit_AllAvailableFruits.createFruit('module_banana.Banana', "Banana 2")
      ..weight = 100
  ]);

  fruits.forEach((fruit){
    print(fruit.toJson());
  });
}

更多关于Flutter原生模块集成插件swift_composer的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter原生模块集成插件swift_composer的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


swift_composer 是一个用于在 Flutter 中集成原生 Swift 模块的插件。它允许你在 Flutter 项目中编写 Swift 代码,并将其与 Dart 代码无缝集成。以下是如何在 Flutter 项目中使用 swift_composer 的基本步骤:

1. 创建 Flutter 项目

首先,创建一个新的 Flutter 项目(如果还没有):

flutter create my_flutter_app
cd my_flutter_app

2. 添加 swift_composer 插件

pubspec.yaml 文件中添加 swift_composer 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  swift_composer: ^0.1.0  # 请使用最新版本

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

3. 创建 Swift 模块

ios/Runner 目录下创建一个新的 Swift 文件,例如 MySwiftModule.swift。在这个文件中,你可以编写 Swift 代码。

import Foundation
import SwiftComposer

@objc class MySwiftModule: NSObject {
    @objc func greet(name: String) -> String {
        return "Hello, \(name)!"
    }
}

4. 注册 Swift 模块

ios/Runner/AppDelegate.swift 中注册你的 Swift 模块,以便 Flutter 可以调用它。

import UIKit
import Flutter
import SwiftComposer

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller = window?.rootViewController as! FlutterViewController
        SwiftComposer.register(module: MySwiftModule.self)
        
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

5. 在 Dart 中调用 Swift 方法

在 Dart 代码中,你可以通过 SwiftComposer 调用 Swift 模块中的方法。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Swift Composer Example'),
        ),
        body: Center(
          child: FutureBuilder<String>(
            future: SwiftComposer.invokeMethod('MySwiftModule.greet', {'name': 'Flutter'}),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return CircularProgressIndicator();
              } else if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              } else {
                return Text('Response: ${snapshot.data}');
              }
            },
          ),
        ),
      ),
    );
  }
}

6. 运行项目

确保你已经连接了 iOS 设备或模拟器,然后运行项目:

flutter run
回到顶部