Flutter 组件化开发实践概述

业务背景:

最近在做一个卡片式的首页模块,这个模块最终会应用到三个app的iOS和Android端,大部分业务相同,但也有一些差异化的东西

所以就考虑到使用跨平台方案去做,考虑到性能和历史原因,最终选用了Flutter

已现存一个Flutter Module项目,但是项目的耦合度很高,开发时也没有做过结构化的设计,直接拿来复用难度还是比较大的

项目结构:

flutter项目工程结构设计为下图:

Native1.png

简述一下:一个flutter module代表一组业务,一个native项目绑定一个flutter module,一个flutter module绑定多个flutter package。这种结构可灵活应对业务任意组合的场景,生成相应的flutter module

所以,这其中涉及到的工作有:

  • 剥离现存flutter module里的基础模块和工具模块,封装成多个package
  • package设计。例如定义静态接口:如baseUrl、原生bundleId、uid
  • package制作
  • package开发时的测试项目配置或者单元测试

我们在组件化过程遇到的几个问题

一、package代码放在哪?

  • pub官方 发布流程
  • git仓库:上传package到git仓库,在业务pubspec.yaml中如下配置,即可简单依赖你的package,其中ref可以是tag、branch
your_package:
    git:
      url: http://xxxx/xxx/your_package
      ref: 0.0.1
      path: your_package
  • 自建服务器 发布流程

二、package开发时怎么调试?

1. 使用example工程调试

  • 使用flutter create example命令创建示例工程
  • 在example工程的pubspec.yaml文件中引入package相对路径
dependencies:
  flutter:
    sdk: flutter
  your_package:
     path: ../
  • 在.vscode/launch.json中配置example调试入口
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "your_package",
            "cwd": "your_package",
            "request": "launch",
            "type": "dart"
        },
        {
            "name": "debug_example",
            "program": "your_package/example/lib/main.dart",
            "request": "launch",
            "type": "dart",
            "flutterMode": "debug"
        },
    ]
}

2. 单元测试/小部件测试/集成测试

  • 官方文档
  • widget_test.dart文件下的main函数中书写测试代码
void main() {
  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
    // Build our app and trigger a frame.
    await tester.pumpWidget(MyApp());

    // Verify that our counter starts at 0.
    expect(find.text('0'), findsOneWidget);
    expect(find.text('1'), findsNothing);

    // Tap the '+' icon and trigger a frame.
    await tester.tap(find.byIcon(Icons.add));
    await tester.pump();

    // Verify that our counter has incremented.
    expect(find.text('0'), findsNothing);
    expect(find.text('1'), findsOneWidget);
  });
}

三、加载package磁盘资源的正确姿势?

注意:在业务项目或者package项目获取package资源,都需要指明绝对路径

一般资源

// 图片
Image.asset("packages/your_package/images/your_image.png")

// json
await rootBundle.loadString('packages/your_package/jsons/your_json.json');

// 其他资源
依然要'packages/your_package/jsons/your_json.json'传入相关api的路径形参

图片资源

注意:assetName可使用相对路径,但要指明package

Image(image: AssetImage("images/your_image.png", package: 'your_package'))

四、package和外界通信的方式?

建议在package新建dart抽象类,在外界实例化抽象类,把实例作为代理传入package模块

你可能感兴趣的:(Flutter 组件化开发实践概述)