构建自己的 Flutter 混合开发框架
随着 Flutter 的普及,越来越多的公司在移动开发中采用 Flutter,尤其是那些希望以较少的开发资源实现跨平台 UI 的项目。本文将带你构建一个 Flutter 混合开发框架,使 Flutter 可以轻松嵌入到已有的原生 iOS 和 Android 项目中。
一、为什么使用 Flutter 混合开发?
Flutter 混合开发的好处包括:
- 降低开发成本:可以在 Android 和 iOS 上重用代码。
- 提升效率:在原生应用中逐步加入 Flutter 模块,逐步完成迁移。
- 代码复用:能够在多个原生项目中共享 Flutter 模块中的业务逻辑。
二、Flutter 混合开发基本原理
在混合开发中,我们将 Flutter 嵌入为一个子模块,作为 Android 和 iOS 项目中的一个模块。
在原生项目中,通过原生 UI 跳转调用 Flutter 页面,或在 Flutter 中嵌入原生控件。这种方法称为“模块化”集成。
三、构建 Flutter 模块
- 创建 Flutter 模块
通过命令创建一个 Flutter 模块,而不是完整的 Flutter 应用。
创建一个
flutter_library
的模块
flutter create -t module flutter_library
创建完成后,会生成一个 Flutter 模块文件夹 flutter_library。这个文件夹可以作为 Android 或 iOS 项目的一部分。
-
在 Flutter 模块中编写业务逻辑 ...
-
在 lib 文件夹下创建你的业务代码,例如 lib/pages/home.dart。
编写一个简单的 Flutter 界面:
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
MaterialApp(
home: Scaffold(
backgroundColor: Colors.cyanAccent, //ARGB红色
appBar: AppBar(
title: const Text("Flutter Libray"),
leading: IconButton(
onPressed: () {
//TODO:
},
icon: const Icon(Icons.add)),
),
body: const Center(child: Text("Hello Flutter Module"),),
),
);
}
}
- 在 Flutter 模块中设置初始路由 在 main.dart 文件中配置路由,以便 Flutter 能识别 /home 路径:
void main() {
runApp(MaterialApp(
initialRoute: '/home',
routes: {
'/home': (context) => HomePage(),
},
));
}
四、将 Flutter 模块集成到 iOS 项目
1.在 iOS 项目中添加 Flutter 模块, Flutter模块 在Podfile的父目录
打开 iOS 项目的 Podfile,引入 Flutter 模块:
flutter_application_path = './flutter_library'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
target 'iOSDemo' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
pod 'AFNetworking'
# Pods for iOSDemo
install_all_flutter_pods(flutter_application_path)
end
post_install do |installer|
flutter_post_install(installer) if defined?(flutter_post_install)
end
然后,运行pod install
命令安装依赖:
- 调用 Flutter 页面
在 iOS 项目中使用 FlutterViewController 调用 Flutter 页面:
#import "ViewController.h"
#import <Flutter/Flutter.h>
#import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h>
@interface ViewController ()
@property (nonatomic, strong) FlutterEngine *flutterEngine;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_flutterEngine = [[FlutterEngine alloc] initWithName:@"iOSDemo"];
[_flutterEngine run];
[GeneratedPluginRegistrant registerWithRegistry:_flutterEngine];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.flutterEngine.viewController = nil;
FlutterViewController *vc = [[FlutterViewController alloc] initWithEngine:self.flutterEngine nibName:nil bundle:nil];
[vc setInitialRoute:@"/home"];
vc.modalPresentationStyle = UIModalPresentationFullScreen;
FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"com.example.myapp/channel" binaryMessenger:vc.binaryMessenger];
[channel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
if ([call.method isEqualToString:@"sendData"]) {
result(@0);
} else {
result(FlutterMethodNotImplemented);
}
}];
[self presentViewController:vc animated:YES completion:NULL];
}
@end
五、在 Flutter 和原生之间传递数据
1.通过 MethodChannel 传递数据
创建一个 MethodChannel 在 Flutter 和原生代码之间传递消息。
在 Flutter 代码中:
import 'package:flutter/services.dart';
const platform = MethodChannel('com.example.myapp/channel');
Future<void> _sendDataToNative() async {
try {
final result = await platform.invokeMethod('sendData', {"key": "value"});
print("Received from native: $result");
} catch (e) {
print("Error: $e");
}
}
在 Android 中:
new MethodChannel(getFlutterEngine().getDartExecutor(), "com.example.myapp/channel")
.setMethodCallHandler(
(call, result) -> {
if (call.method.equals("sendData")) {
String data = call.argument("key");
result.success("Data received in native: " + data);
} else {
result.notImplemented();
}
}
);
六、总结
通过以上步骤,你就可以构建一个 Flutter 混合开发框架,将 Flutter 嵌入到原生应用中。