Introducción al complemento
Una herramienta de generación de código que hace que Flutter
la comunicación con la plataforma host sea más segura, sencilla y rápida. A través Dart
de la entrada se genera el código de la plantilla común a ambos extremos, y el nativo solo necesita reescribir la interfaz en la plantilla, sin Method Channel
necesidad de implementación de gestión. Los parámetros se pueden generar sincrónicamente a través de plantillas. Esto es realmente conveniente Para las tres formas del sistema, puede consultar este artículo (Tres formas de Flutter y comunicación nativa ).
Información del complemento
Dirección del complemento: pub.flutter-io.cn/packages/pi…
Versión del complemento: paloma: 3.0.3
uso de complementos
Preparativos para Flutter
Cree una carpeta de palomas fuera del directorio lib del proyecto Flutter y cree schema.dart en la carpeta de palomas
Debido a que actualmente es una combinación de nativo y Flutter, necesito obtener información de usuario y localHost de nativo, por lo que el código de schema.dart es el siguiente
/// Description : 定义与原生通信--通过自动生成减少手写代码量
/// 请求参数和返回结果都必需是类结构 否则无法生成文件
/// - Flutter 调用 Native 方法 ( @HostApi() )
/// - Native 调用 Flutter 方法 ( @FlutterApi() )
///Flutter 调用原生代码
@HostApi()
abstract class UserInfoApi {
///获取用户信息
UserInfo getUserInfo();
///获取LocalHost用于抓包
String getLocalHost();
}
///用户信息实体类
class UserInfo {
String? userId;
String? realName;
String? phone;
String? headImg;
}
复制代码
comando usado
命令拆解:
①` flutter pub run pigeon`
生成代码的命令
②` --input pigeons/schema.dart `
指定生成代码的输入`dart`文件
③ `--dart_out lib/schema.dart `
指定输出生成`dart`文件的目录文件
④ `--objc_header_out ios/Flutter/FlutterPluginRegistrant/Classes/schema.h `
指定要生成的`iOS`的`.h`文件路径
⑤ `--objc_source_out ios/Flutter/FlutterPluginRegistrant/Classes/schema.m `
指定要生成的`iOS`的`.m`文件路径
⑥ `--java_out android/Flutter/src/main/java/io/flutter/plugins/Schema.java `
指定要生成的`Android`的`.java`文件路径
⑦ `--java_package "io.flutter.plugins`
指定`Android`的包名,在`android/src/main/`下的`AndroidManifest.xml`里的`package`
⑧ `--objc_prefix Z`(可选)指定生成OC文件的前缀为Z,前缀自己定义为自己的。
复制代码
En el directorio del proyecto ~/flutter_pigeon_plugin
, es demasiado problemático ejecutar el comando directamente, aquí creé un script, y es suficiente ejecutar el script directamente cada vez que hay una actualización.
Crear guión
Este script está escrito de acuerdo con el comando anterior, y este también es el script run pigeon.sh creado en la carpeta de palomas.
flutter pub run pigeon \
--input pigeons/schema.dart \
--dart_out lib/schema.dart \
--objc_header_out ios/Flutter/FlutterPluginRegistrant/Classes/schema.h \
--objc_source_out ios/Flutter/FlutterPluginRegistrant/Classes/schema.m \
--java_out android/Flutter/src/main/java/io/flutter/plugins/Schema.java \
--java_package "io.flutter.plugins"
# 点击绿色三角形按钮,或者选择文件右键选择运行此文件,开启运行以上脚本文件,
# 然后会自动生产跨端通信的Android文件(Java文件)和iOS文件(Object_C)
No newline at end of file
复制代码
Este es el archivo que se genera automáticamente después de ejecutar el script
¿Cómo comunicarse?
Por ejemplo: no escribí dos métodos arriba, entonces si quiero capturar paquetes, necesito configurarlo en la ip de Mac
Código lateral de aleteo
if (!kReleaseMode){
UserInfoApi().getLocalHost().then((value) {
if(value.isNotEmpty){
(_dio!.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) {
client.findProxy = (uri) {
return "PROXY $value:8888";
};
};
}
});
}
复制代码
código nativo
En primer lugar, se debe introducir el módulo Flutter en el proyecto nativo, que no se explicará aquí. Creó una clase que hereda de FlutterViewController
- (void)viewDidLoad {
[super viewDidLoad];
[GeneratedPluginRegistrant registerWithRegistry:self.engine];
//这里是需要传入一个对象的
UserInfoApiSetup(self.binaryMessenger, [UserInfoAPI new]);
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden = YES;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.navigationController.navigationBarHidden = NO;
}
复制代码
También debe crear una clase que siga el protocolo UserInfoApi e implemente los métodos del protocolo.
@interface UserInfoAPI : NSObject<UserInfoApi>
@end
@implementation UserInfoAPI
- (nullable UserInfo *)getUserInfoWithError:(FlutterError * _Nullable __autoreleasing * _Nonnull)error {
UserInfo *userInfo = [[UserInfo alloc] init];
return userInfo;
}
- (nullable NSString *)getLocalHostWithError:(FlutterError * _Nullable * _Nonnull)error {
return @"10.210.3.16";
}
@end
复制代码
La página Flutter vuelve a la página nativa
De esta manera, Flutter puede llamar al método nativo. Generalmente, saltamos a la página de Flutter. Si queremos volver a la página nativa, también podemos lograrlo. Al llamar al método nativo, regresa el procesamiento nativo, como el El lado de iOS puede lograr esto.
if ([mthodStr isEqualToString:@"closeFlutterVC"]) {
//调用popViewControllerAnimated
}
复制代码
Flutter返回Android端则直接可以调用方法完成
SystemNavigator.pop();
复制代码
原生进入Flutter页面
//这里可以传入要进入flutter页面的路由
TestViewController *flutterVC = [[IAskFlutterViewController alloc] initWithProject:nil initialRoute:@"" nibName:nil bundle:nil];[self.navigationController pushViewController:flutterVC animated:YES];
复制代码
Android端其实也是同理,实现getInitialRoute
方法,返回要跳转页面的路由即可。
Flutter集成iOS原生遇到的问题汇总:
下面列举一些最近在进行混编时遇到的一些问题:
Failed to register observatory port with mDNS with error -65555.
官方描述
On iOS 14 and higher, enable the Dart multicast DNS service in the Debug version of your app to add debugging functionalities such as hot-reload and DevTools via flutter attach.
解决方法
- 将应用程序的Info.plist重命名为Info-Debug.plist。复制一个名为Info-Release.plist的副本,并将其添加到Xcode项目中
- 在Info-Debug.plist中,添加键
Bonjour services
并将值设置为_dartobservatory._tcp
可选的设置Privacy - Local Network Usage Description
,并将值设置为Allow Flutter tools on your computer to connect and debug your application.This prompt will not appear on release builds.
- 在TARGETS中, build settings 修改 Info.plist File 路径 path/to/Info.plist 为
path/to/Info-$(CONFIGURATION).plist
.
In iOS 14+,debug mode Flutter apps can only be launched from Flutter tooling,IDEs with Flutter pl...
分析原因
在 iOS14 的真机上安装了 debug模式 编译出来的 flutter 应用,那么在断开编译安装连接后,将无法从桌面上打开该应用程序
解决方案
- 使用flutter的release模式,终端输入
flutter run --release
复制代码
- Modificar la configuración de main.dart
Motivo: probado: '/usr/lib/swift/App.framework/App' (no existe tal archivo), '/usr/lib/swift/App.framework/App' (no existe tal archivo),
Analiza las razones
Flutter
no es App.framework
importado
Solución
Abra Pods-xx-frameworks.sh
y agregue el siguiente código
install_framework "${PODS_ROOT}/../flutter/.ios/Flutter/App.framework"
No se encontró podspec para Flutter
en../flutter/.ios/Flutter/engine
Analiza las razones
Falta este archivo en esta ruta
Solución
Puedes ver si este archivo se copia directamente en otros proyectos de Flutter.Este es el archivo relacionado con el motor de Flutter. Si hay una carpeta ios, vea si hay ese archivo debajo de este archivo
Símbolo indefinido: OBJC_CLASS $_TestViewController
Analiza las razones
Esta es una clase que creé que hereda de FlutterViewController y no la encontré
Solución
Agregue el archivo .m para esta clase en este
El widget inferior no sigue el teclado y rebota
Analiza las razones
El valor predeterminado resizeToAvoidBottomInset: true, dentro de Scaffold mediaQuery.viewInsets.bottom participará en el cálculo del tamaño de BoxConstraints, es decir, ajustará la posición inferior interna para coincidir con el teclado cuando este rebote.
Solución
configurarresizeToAvoidBottomInset: false
Seguiré actualizando si encuentro nuevos problemas en el futuro~
Resumir
Dado que el método de comunicación nativo se usaba en el pasado, era realmente problemático y la forma de usar este complemento es relativamente simple. Pero esto hace que la lectura del código sea un poco más difícil, no es tan legible como la comunicación nativa directa, todo tiene dos caras y depende de ti medirlo.