iOS项目(Swift),使用Flutter进行混合开发

一、创建flutter_module

先创建flutter module项目,参考官方文档,先cd至目标文件夹,执行命令为

flutter create --template module flutter_module

创建成功后,打开flutter_module项目,打开pubspec.yaml文件,添加所需的依赖

 执行命令,更新依赖。

执行 flutter run 命令,生成pod

创建Swift项目,打开Swift项目中的 Podfile添加相关pod命令

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

flutter_application_path = './flutter_module模块项目'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

target 'FlutterMixTest' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!

# flutter
install_all_flutter_pods(flutter_application_path)
# Pods for FlutterMixTest
 
end

post_install do |installer|
flutter_post_install(installer) if defined?(flutter_post_install)
end

执行pod install命令(每次 flutter_module 中的 pubspec.yaml 更改后,都需要再次执行 pod install 命令)

 

我们在应用启动时的 App Delegate 中创建了一个 FlutterEngine 并作为属性暴露给外界。

在 SceneDelegate.swift 中

或 在 AppDelegate.swift:

 在view controller中使用

 

 

二、Flutter与原生通信

Flutter 与原生之间的通信依赖灵活的消息传递方式

  • 应用的Flutter部分通过平台通道(platform channel)将消息发送到其应用程序的所在的宿主(iOS或Android)应用(原生应用)

  • 宿主监听平台通道,并接收该消息。然后它会调用该平台的 API,并将响应发送回客户端,即应用程序的 Flutter 部分

Flutter 与原生存在三种交互方式

  • MethodChannel:用于传递方法调用(method invocation)通常用来调用 native 中某个方法

  • BasicMessageChannel:用于传递字符串和半结构化的信息,这个用的比较少

  • EventChannel:用于数据流(event streams)的通信。有监听功能,比如电量变化之后直接推送数据给flutter端

三种 Channel 之间互相独立,各有用途,但它们在设计上却非常相近。每种 Channel 均有三个重要成员变量:

  • name: String类型,代表 Channel 的名字,也是其唯一标识符

  • messager:BinaryMessenger 类型,代表消息信使,是消息的发送与接收的工具

  • codec: MessageCodec 类型或 MethodCodec 类型,代表消息的编解码器

1、MethodChannel 的使用

 Flutter端代码:

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

class MethodChannelDemo extends StatefulWidget {
const MethodChannelDemo({Key? key}) : super(key: key);

@override
_MethodChannelDemoState createState() => _MethodChannelDemoState();
}

class _MethodChannelDemoState extends State<MethodChannelDemo> {
//初始化 MethodChannel
var channel = const MethodChannel("com.flutter.guide.MethodChannel");

var _data;
var _nativeData;

@override
void initState() {
// TODO: implement initState
super.initState();

//监听并接收原生数据
channel.setMethodCallHandler((MethodCall call) async {
debugPrint("$call");
if (call.method == "sendData2") {
setState(() {
var name = call.arguments["name"];
var age = call.arguments["age"];
_nativeData = '$name,$age';
});
}
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('MethodChannel'),
centerTitle: true,
),
body: Column(
children: [
const SizedBox(
height: 50,
),
ElevatedButton(
onPressed: () async {
//向原生端 发送数据
var result = await channel
.invokeMethod('sendData', {'name': 'laomeng', 'age': 18});
var name = result['name'];
var age = result['age'];

debugPrint("--原生返回的数据---$result");
setState(() {
_data = '$name,$age';
});
},
child: const Text('发送数据到原生'),
),
Text('原生返回数据:$_data'),
Text('接收到原生返回数据:$_nativeData')
],
),
);
}
}

进入flutter页面,接收到原生数据:

点击发送数据到原生按钮,原生返回数据如下:

 

2、BasicMessageChannel的使用

它是可以双端通信的,Flutter 端可以给 iOS 发送消息,iOS 也可以给 Flutter 发送消息。

 iOS端代码:

 Flutter端代码:

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

class BasicMessageChannelDemo extends StatefulWidget {
  const BasicMessageChannelDemo({Key? key}) : super(key: key);

  @override
  _BasicMessageChannelDemoState createState() =>
      _BasicMessageChannelDemoState();
}

class _BasicMessageChannelDemoState extends State<BasicMessageChannelDemo> {
  //Flutter 端创建 MethodChannel 通道,用于与原生端通信:
  var channel = const BasicMessageChannel(
      'com.flutter.guide.BasicMessageChannel', StandardMessageCodec());
  var _data;
  var _nativeData;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    //监听并接收原生数据
    channel.setMessageHandler((message) async {
      setState(() {
        _nativeData = message;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('BasicMessageChannel'),
        centerTitle: true,
      ),
      body: Column(
        children: [
          const SizedBox(
            height: 50,
          ),
          ElevatedButton(
            onPressed: () async {
              //向原生发送数据
              var result = await channel.send({'name': 'laowang', 'age': 25});
              // var name = result['name'];
              // var age = result['age'];
              setState(() {
                _data = '$result';
              });
            },
            child: const Text('发送数据到原生'),
          ),
          Text('原生返回数据:$_data'),
          Text('接收到原生发送的数据:$_nativeData'),
        ],
      ),
    );
  }
}

 3、EventChannel的使用

只能是原生发送消息给 Flutter 端,例如监听手机电量变化,网络变化,传感器等。

iOS端代码:

 Flutter端代码:

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

class EventChannelDemo extends StatefulWidget {
  const EventChannelDemo({Key? key}) : super(key: key);

  @override
  _EventChannelDemoState createState() => _EventChannelDemoState();
}

class _EventChannelDemoState extends State<EventChannelDemo> {
  //Flutter 端创建 EventChannel 通道,用于与原生端通信:
  //com.flutter.guide.EventChannel 是 EventChannel 的名称,原生端要与之对应。
  final _eventChannel = const EventChannel('com.flutter.guide.EventChannel');
  var _data;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    //监听原生端发送的消息:
    _eventChannel.receiveBroadcastStream().listen(_onData);
  }

  _onData(event) {
    setState(() {
      _data = event;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("EventChannelDemo"),
        centerTitle: true,
      ),
      body: Center(
        child: Text('$_data'),
      ),
    );
  }
}

 

 

使用链接:https://flutter.cn/docs/development/add-to-app/ios/add-flutter-screen?tab=vc-uikit-swift-tab

 

posted @ 2023-11-09 22:42  玉米炖排骨  阅读(404)  评论(0编辑  收藏  举报