Flutter 和iOS混合开发(二)

1,915 阅读3分钟

1.原生的向fluter 也页面传值

首先需要在flutter 引入

import 'dart:ui';

引入以后我们可以取到 window,window含有一个window.defaultRouteName属性

那么这个属性在iOS原生工程的FlutterViewController类有一个与之对应的方法

/**

  • Sets the first route that the Flutter app shows. The default is "/".
  • This method will guarnatee that the initial route is delivered, even if the
  • Flutter window hasn't been created yet when called. It cannot be used to update
  • the current route being shown in a visible FlutterViewController (see pushRoute
  • and popRoute).
  • @param route The name of the first route to show. */
  • (void)setInitialRoute:(NSString*)route;

我的测试代码 iOS

FlutterViewController * flutterVc = [[FlutterViewController alloc] init];

[flutterVc setInitialRoute:@"wincer"];

[self presentViewController:flutterVc animated:YES completion:^{
    
}];

Flutter 代码

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

void main() => runApp(MyApp(pageIndex:window.defaultRouteName));

class MyApp extends StatelessWidget { final String pageIndex;

const MyApp({Key key, this.pageIndex}) : super(key: key); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( // This is the theme of your application. // // Try running your application with "flutter run". You'll see the // application has a blue toolbar. Then, without quitting the app, try // changing the primarySwatch below to Colors.green and then invoke // "hot reload" (press "r" in the console where you ran "flutter run", // or press Run > Flutter Hot Reload in a Flutter IDE). Notice that the // counter didn't reset back to zero; the application is not restarted. primarySwatch: Colors.blue, ), home: rootpage(pageIndex) , ); } }

Widget rootpage(String pageIndex){

** print(pageIndex);** return Container( ** child: Text(pageIndex)**

); }

flutter 代码加载的部分为我更改的,你可以与源代码比较

效果图

flutter 的打印在xcode可以看到

我们正常的混合开发肯定是需要某些页面是flutter写的,那么我们可以根据window.defaultRouteName这个去指定调到那个页面

2.返回到原生

现在我们可以跳到flutter ,我们也需要跳回去

那么就需要在flutter 引入 import 'package:flutter/services.dart';

这个service 含有一个channel,我们就是根据这个channel去和iOS原生通讯了! const MethodChannel(this.name, [this.codec = const StandardMethodCodec()]); 这个channel 有两个参数,第一是name,这个name就是一个标识符,唯一的 codec就是是否不要进行类型转换的!比如flutter 的string 转换成iOS 的NSString

MethodChannel这个方法相当于我们的通知,在iOS内也需要注册下

那么这 MethodChannel 改怎么发送通知呢? MethodChannel('wincer_flutter').invokeMapMethod(method) 后面的method相当于我们iOS的Sel

这个method 就是调用我们原生的方法,如果需要参数,后面可以加上参数,用,分割

Flutter示例代码 MethodChannel('wincer_flutter').invokeMapMethod('

','13123123');

那么我们在iOS也需要创建一个 FlutterMethodChannel

FlutterMethodChannel * methodChennel = [FlutterMethodChannel methodChannelWithName:@"wincer_flutter" binaryMessenger:flutterVc];

withName的参数就是flutter channel 的name, binaryMessenge:就是创建的flutterVC

那么这个FlutterMethodChannel有一个句柄, [methodChennel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) { NSLog(@"%@\n%@",call.method,call.arguments); }];

我们可以看到block回调内有有个call,call有两个信息 call.method 方法名字 call.arguments flutter传的参数

这样我们就可以根据获取到的call.methond 进行我们想做的操作了!

==========================================

我们可以猜想下,FlutterMethodChannel 可以用于flutter给iOS传参,那么这个东西是不是也可以用于iOS给flutter 传参呢!

这两个平台的使用 FlutterMethodChannel完全一样,

ios 原生向flutter 传值 于flutter向原生类似。

FlutterMethodChannel * methodChennel = [FlutterMethodChannel methodChannelWithName:@"wincer_flutter" binaryMessenger:flutterVc];

[methodChennel invokeMethod:@"onePage" arguments:nil];

flutter接收也是类似

final MethodChannel _oneChanel = MethodChannel('onePage');

_oneChanel.setMethodCallHandler((MethodCall call){ _pageIndex = call.method; setState(() {

  });
}

对比下,是不是完全相同,

但是此时我发现一个问题,跳进flutter ,然后退出到原生,再跳flutter ,内存只增不减,

其实我这里是FlutterViewController写成了局部变量,这个东西不会释放的,而且整个flutter在我们原生里只有一个FlutterViewController就够用了!所以开发时候只需创建一个就可以了

写的比较粗糙,比较乱,如有需要评论,我会主动联系你的

喷我的直接评论就好了!