「这是我参与2022初次更文应战的第3天,活动详情检查:2022初次更文应战」

原生嵌入Flutter-Flutter module

如果你希望Flutter代码可以被原生所嵌入,那么此时应该这么创立官方教程一个Flutter module

cd some/path/
flutter create --template module my_flutter

Flutter进阶-混合开发下篇

此时看下其时的目录结构command+ shift+.显现躲藏文件,可以看到这里边也有.android文件和.ios文件,这里首要是为了做调试用的,不主张在这两个文件中增加任何的代码。因为这里是要嵌入到原生中,所以在.android文件和.ios文件中的任何修正都不会被打包到原生的项目中去的。 ​

首要的代码仍是写在main.dart

Flutter进阶-混合开发下篇

iOS中集成Flutter module

接着我们创立一个空的iOS工程,示例是跟其时的my_flutter放在同一目录下,如下图所示

Flutter进阶-混合开发下篇
我运用的CocoaPods来集成,在iOS工程MyFlutterpod init,翻开该Podfile文件,在Podfile中增加下面的代码

flutter_application_path = '../my_flutter'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
target 'MyApp' do
  install_all_flutter_pods(flutter_application_path)
end

然后运转pod install,翻开iOS的工程试下**import Flutter**如果能成功,就标明已经在原生的工程中加上了Flutter的代码。

private let flutterVc = FlutterViewController()
@objc
private func tap1() {
   self.present(flutterVc, animated: true, completion: nil)
}

Flutter进阶-混合开发下篇

留心:此时我们观察一下内存,可以看到当调用起Flutter相关代码的时分,内存的情况:从30MB直奔100+MB,并且我dissmiss掉其时的FlutterVC时,这个内存并没有减少,加载了就会一直在内存中了。

Flutter进阶-混合开发下篇
Products-> MyFlutter->Show in Finder-> 显现包内容->Frameworks

Flutter进阶-混合开发下篇

可以看到多的其实就是这些内容:Flutter烘托引擎和一些资源内容。

setRoute路由

通过路由来区别跳转页面,现在已经抛弃了,但是我们仍是可以实验一下:

- (void)setInitialRoute:(NSString*)route
    FLUTTER_DEPRECATED("Use FlutterViewController initializer to specify initial route");

在iOS原生项目中,再创立一个按钮,点击不同的按钮跳转不同的Flutter页面

    @objc
    private func tap1() {
      let flutterVc = FlutterViewController()
       flutterVc.setInitialRoute("one")
       self.present(flutterVc, animated: true, completion: nil)
    }
    @objc
    private func tap2() {
      let flutterVc = FlutterViewController()
      flutterVc.setInitialRoute("two")
      self.present(flutterVc, animated: true, completion: nil)
    }

在Flutter中怎样实现呢?window.defaultRouteName这个就是从原生传递过来的值

import 'dart:ui';
import 'package:flutter/material.dart';
void main() => runApp(MyApp(
      pageIndex: window.defaultRouteName,
    ));
class MyApp extends StatelessWidget {
  final String pageIndex;
  const MyApp({Key? key, required this.pageIndex}) : super(key: key);
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Demo',
      home: Scaffold(
        appBar: AppBar(title: Text(pageIndex)),
        body: Center(child: Text(pageIndex)),
      ),
    );
  }
}

command + shift + k根除iOS的缓存从头运转试下。ok了~

Flutter进阶-混合开发下篇

Channel定义的三种方法

Flutter定义了三种不同的Channel

  1. MethodChannel:传递方法调用,一次通讯
  2. BasicMessageChannel:持续通讯,收到消息之后还可以回复消息
  3. EventChannel:数据流,持续通讯

MethodChannel

我们也可以运用MethodChannel来通讯invokeMapMethod <==> setMethodCallHandler 在flutter中代码如下:

onPressed: () {
  // 通讯
  const MethodChannel('one').invokeMapMethod('exit');
},

在swift中对应的回调,这样点击中心的按钮就能dismiss掉。

    @objc
    private func tap1() {
        let methodChannel = FlutterMethodChannel(name: "one", binaryMessenger: self.flutterVc as! FlutterBinaryMessenger)
        methodChannel.setMethodCallHandler { call, result in
            if call.method == "exit"{
                self.dismiss(animated: true, completion: nil)
            }
        }
        self.present(flutterVc, animated: true, completion: nil)
    }

Flutter进阶-混合开发下篇

BasicMessageChannel

运用BasicMessageChannel的方法和上面的基本差不多,但是已然说了是持续通讯,那么运用TextField来验证下: send <==> setMethodCallHandler

  BasicMessageChannel _channel =
      const BasicMessageChannel('messageChannel', StandardMessageCodec());
// ...
 	TextField(
    onChanged: (String str) {
       _channel.send(str);
    },
@override
  void initState() {
    // TODO: implement initState
    super.initState();
    _channel.setMessageHandler((message) {
      print('收到来自iOS的$message');
      return Future(() {});
    });
  }
    override func viewDidLoad() {
        super.viewDidLoad()
        messageChannel = FlutterBasicMessageChannel(name: "messageChannel", binaryMessenger: self.flutterVc.binaryMessenger)
        messageChannel.setMessageHandler { data, reply in
            print("收到了Flutter的数据\(String(describing: data))")
        }
    }
  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        a += 1;
        self.messageChannel.sendMessage("\(a)")
    }

Flutter进阶-混合开发下篇