如何实现 Flutter 与原生的混合开发方式?详解Flutter混合开发的路由栈管理(深度好文)

2023-01-02 0 672

为的是把 Flutter 导入到原生植物工程建设,他们须要把 Flutter 工程建设改建为原生植物工程建设的两个组件倚赖,并以组件化的形式管理工作相同网络平台的 Flutter 构筑乙醛,即 Android 网络平台选用 aar、iOS 网络平台选用 pod 展开倚赖管理工作。这样,他们就能在 Android 工程建设中透过 FlutterView,iOS 工程建设中透过 FlutterViewController,为 Flutter 构筑应用出口处,同时实现 Flutter 与原生植物的混和合作Attichy。

对混和合作开发的应用领域而言,一般而言他们只会将应用领域的部份组件修正成 Flutter 合作开发,其他组件继续留存原生植物合作开发,因此应用领域内除 Flutter 的网页之外,还会有原生植物 Android、iOS 的网页。在这种情况下,Flutter 网页有可能会须要重定向到原生植物网页,而原生植物网页也可能会须要重定向到 Flutter 网页。这就牵涉到了两个捷伊难题:怎样标准化管理工作原生植物网页和 Flutter 网页重定向可视化的混和导航系统栈。

混和导航系统栈

混和导航系统栈,指的是在混和合作开发中原地区生植物网页和Flutter网页互相参杂,存有于使用者视点的网页导航系统栈快照,如图11-12右图。在混和合作开发的应用领域中,原生植物Android、iOS与Flutter各别同时实现了两套彼此间完全相同的网页态射监督机制,原生植物网络平台选用的是单罐子单网页,即两个ViewController或Activity相关联两个原生植物网页;而Flutter选用单罐子多网页的监督机制,即两个ViewController或Activity相关联数个Flutter网页。Flutter在原生植物的导航系统栈其内又自有了两套Flutter导航系统栈,这使原生植物网页与Flutter网页与间展开网页转换时,须要处置跨发动机的网页转换难题。

如何实现 Flutter 与原生的混合开发方式?详解Flutter混合开发的路由栈管理(深度好文)

接下去,他们就依次从原生植物网页重定向至 Flutter 网页,以及从 Flutter 网页重定向至原生植物网页来看一看混和合作开发的路由器管理工作。

原生植物网页重定向Flutter网页

从原生植物网页重定向至 Flutter 网页,同时实现起来非常简单。因为 Flutter 这类借力如在植物提供更多的罐子,即iOS 选用的是FlutterViewController,Android 选用的是Activity 中的 FlutterView。所以他们透过调用 Flutter 罐子,为其增设如上所述路由器网页后,就能以原生植物的形式重定向至 Flutter 网页了。

对iOS混和工程建设而言,能先调用两个FlutterViewController示例,接着增设调用网页路由器,将其重新加入原生植物的快照导航系统栈中方可顺利完成重定向,如下表所示右图。

//iOS 重定向至Flutter网页 FlutterViewController *vc = [[FlutterViewController alloc] init]; //增设Flutter调用路由器网页 [vc setInitialRoute:@”defaultPage”]; //顺利完成网页重定向 [self.navigationController pushViewController:vc animated:YES];

对Android混和工程建设而言,则须要多加一步。因为Flutter网页的出口处并不是原生植物快照导航系统栈的最小单位Activity,而是两个FlutterView,所以我们须要把这个View包装到Activity的contentView中,接着才能同时实现重定向。在Activity内部增设网页调用路由器后,在外部就能选用打开两个普通的原生植物快照的形式来打开Flutter页面了,如下表所示右图。

//Android 重定向至Flutter网页 //创建两个作为Flutter网页罐子的Activity public class FlutterHomeActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //增设Flutter调用路由器网页,传入路由器标识符 View FlutterView = Flutter.createView(this, getLifecycle(), “defaultRoute”); //用FlutterView替代Activity的ContentView setContentView(FlutterView); } } //用FlutterPageActivity顺利完成网页重定向 Intent intent = new Intent(MainActivity.this, FlutterHomeActivity.class); startActivity(intent);

运行项目代码,最终的效果下图右图。

如何实现 Flutter 与原生的混合开发方式?详解Flutter混合开发的路由栈管理(深度好文)

对Android混和工程建设而言,Flutter的原生植物罐子就是两个Activity,只须要创建两个FlutterView,接着利用addContentView()方法将当前网页的layout网页布局添加进去方可。如果Flutter的原生植物罐子是两个Fragment,那么只须要创建两个FlutterFragment,接着在指定的罐子中添加Flutter网页方可。同样,对iOS混和工程建设而言,Flutter的原生植物罐子是两个FlutterViewController。

Flutter 网页重定向至原生植物网页

相比原生植物网页重定向Flutter网页,从Flutter网页重定向至原生植物网页则会相对麻烦些。因为他们须要考虑以下两种场景,即从Flutter网页打开捷伊原生植物网页和从Flutter网页回退到旧的原生植物网页。

由于Flutter并没有提供更多对原生植物网页的操作方法,所以不能透过直接调用原生植物网络平台的方法来同时实现网页重定向,不过能选用Flutter提供更多的方法通道来间接同时实现,即打开原生植物网页选用的是openNativePage()方法,须要关闭Flutter网页时则调用closeFlutterPage()方法。

具体而言,在Flutter和原生植物两端各别调用方法通道,并提供更多Flutter操作原生植物网页的方法,并在原生植物代码中注册方法通道,当原生植物端收到Flutter的方法调用时就能打开捷伊原生植物网页。

在混和合作开发的应用领域中,FlutterView与FlutterViewController是Flutter组件的出口处,也是Flutter组件调用的地方。能看到,在混和合作开发的应用中接入Flutter与合作开发两个纯Flutter应用领域在运行监督机制上并无任何区别,因为对混和工程建设而言,原生植物工程建设只不过是为Flutter提供更多了两个罐子而已,即Android选用的是FlutterView,iOS选用的是FlutterViewController。接下去,Flutter组件就能选用自己的导航系统栈来管理工作Flutter网页,并且能同时实现数个复杂网页的渲染和转换。

因为Flutter罐子这类属于原生植物导航系统栈的一部份,所以当Flutter罐子内的根网页须要返回时,合作开发者须要处置Flutter罐子的关闭难题,从而同时实现Flutter根网页的关闭。由于Flutter并没有提供更多操作Flutter罐子的方法,因此他们依然须要透过方法通道,在原生植物代码宿主为Flutter提供更多操作Flutter罐子的方法,在网页返回时关闭Flutter网页。如图下图右图,是Flutter重定向原生植物网页的两种场景的示意图。

如何实现 Flutter 与原生的混合开发方式?详解Flutter混合开发的路由栈管理(深度好文)

选用方法通道同时实现Flutter网页至原生植物网页的重定向,注册方法通道最合适的地方是Flutter应用领域的出口处,即在iOS端的FlutterViewController和Android端的是FlutterView调用Flutter网页之前。因此,在混和合作开发的应用领域中,须要依次继承iOS的FlutterViewController和Android的AppCompatActivity,接着在iOS的viewDidLoad和Android的onCreate生命周期函数中调用Flutter罐子时,注册openNativePage和closeFlutterPage两个方法。

下面是选用方法通道同时实现Flutter重定向原生植物网页的原生植物Android端的代码,如下表所示右图。
public class FlutterModuleActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); //调用Flutter罐子 FlutterView fv = Flutter.createView(this, getLifecycle(), “defaultPage”); //注册方法通道 new MethodChannel(fv, “com.xzh/navigation”).setMethodCallHandler( new MethodChannel.MethodCallHandler() { @Override public void onMethodCall(MethodCall call, Result result) { if (call.method.equals(“openNativePage”)) { Intent intent = new Intent(this, AndroidNativeActivity.class); tartActivity(intent); result.success(0); } else if (call.method.equals(“closeFlutterPage”)) { finish(); result.success(0); } else { result.notImplemented(); } } }); setContentView(fv); } }

能发现,在上面的代码中,首先选用FlutterView调用两个Flutter罐子,接着在原生植物代码中注册openNativePage和closeFlutterPage两个方法,当Flutter网页透过方法通道调用原生植物方法时方可打开原生植物网页。

与原生植物Android端的同时实现原理类似,选用方法通道同时实现网页的重定向页须要在原生植物iOS端中注册openNativePage和closeFlutterPage两个方法,代码如下表所示。
@interface FlutterHomeViewController : FlutterViewController @end @implementation FlutterHomeViewController – (void)viewDidLoad { [super viewDidLoad]; //声明方法通道 FlutterMethodChannel* channel = [FlutterMethodChannel methodChannelWithName:@”com.xzh/navigation” binaryMessenger:self]; [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { if([call.method isEqualToString:@”openNativePage”]) { //打开两个捷伊原生植物网页 iOSNativeViewController *vc = [[iOSNativeViewController alloc] init]; [self.navigationController pushViewController:vc animated:YES]; result(@0); }else if([call.method isEqualToString:@”closeFlutterPage”]) { //关闭Flutter网页 [self.navigationController popViewControllerAnimated:YES]; result(@0); }else { result(FlutterMethodNotImplemented); } }]; } @end

经过上面的方法注册后,接下去就能在Flutter中选用openNativePage()方法来打开原生植物网页了,如下表所示右图。

void main() =Channel(com.xzh/navigation); //根据路由器标识符返回应用领域出口处快照 Widget _widgetForRoute(String route) { switch (route) { default://返回默认快照 return MaterialApp(home:DefaultPage()); } } class PageA extends StatelessWidget { … @override Widget build(BuildContext context) { return Scaffold( body: RaisedButton( child: Text(“Go PageB”), onPressed: ()=>platform.invokeMethod(openNativePage)//打开原生植物网页 )); } } class DefaultPage extends StatelessWidget { … @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(“DefaultPage Page”), leading: IconButton(icon:Icon(Icons.arrow_back), onPressed:() => platform.invokeMethod(closeFlutterPage)//关闭Flutter网页 )), body: RaisedButton( child: Text(“Go PageA”), onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (context) => PageA())),//打开Flutter网页 PageA )); } }

在上面的例子中,Flutter 罐子的根快照 DefaultPage 包含有两个按钮。点击左上角的按钮后,能透过 closeFlutterPage 返回原生植物网页;点击中间的按钮后,会打开两个捷伊 Flutter 网页 PageA。PageA 中也有两个按钮,点击这个按钮后会调用 openNativePage 来打开两个捷伊原生植物网页。

整个混和导航系统栈示例的代码流程,如下表所示图右图。透过这张图,你就能把这个示例的整个代码流程串起来了。

如何实现 Flutter 与原生的混合开发方式?详解Flutter混合开发的路由栈管理(深度好文)

在混和应用领域工程建设中,RootViewController 与 MainActivity 依次是 iOS 和 Android 应用领域的原生植物网页出口处,能调用为 Flutter 罐子的 FlutterHomeViewController(iOS 端)与 FlutterHomeActivity(Android 端)。

在为其增设如上所述路由器网页 DefaultPage 后,就能以原生植物的形式重定向至 Flutter 网页。但是,Flutter 并未提供更多接口,来支持从 Flutter 的 DefaultPage 网页返回到原生植物网页,因此他们须要利用方法通道来注册关闭 Flutter 容器的方法,即 closeFlutterPage,让 Flutter 罐子接收到这个方法调用时关闭自身。

在 Flutter 罐子内部,他们能选用 Flutter 内部的网页路由器监督机制,透过 Navigator.push 方法,顺利完成从 DefaultPage 到 PageA 的网页重定向;而当他们想从 Flutter 的 PageA 网页重定向到原生植物网页时,因为牵涉到跨发动机的网页路由器,所以他们仍然须要利用方法通道来注册打开原生植物网页的方法,即 openNativePage,让 Flutter 罐子接收到这个方法调用时,在原生植物代码宿主顺利完成原生植物网页 SomeOtherNativeViewController(iOS 端)与 SomeNativePageActivity(Android 端)的调用,并最终顺利完成网页重定向。

总结

对如在植物 Android、iOS 工程建设混编 Flutter 合作开发,由于应用领域中会同时存有 Android、iOS 和 Flutter 网页,所以他们须要妥善处置跨渲染发动机的网页重定向,解决原生植物网页怎样转换 Flutter 网页,以及 Flutter 网页怎样转换到原生植物网页的难题。

在原生植物网页转换到 Flutter 网页时,他们一般而言会将 Flutter 罐子封装成两个独立的 ViewController(iOS 端)或 Activity(Android 端),在为其增设好 Flutter 罐子的网页调用路由器(即根快照)后,原生植物的代码就能按照打开两个普通的原生植物网页的形式来打开 Flutter 网页了。

而如果他们想在 Flutter 网页重定向到原生植物网页,则须要同时处置好打开捷伊原生植物网页,以及关闭自身回退到老的原生植物网页两种场景。在这两种场景下,他们都须要利用方法通道来注册相应的处置方法,从而在原生植物代码宿主同时实现新网页的打开和 Flutter 罐子的关闭。

须要注意的是,与纯 Flutter 应用领域相同,原生植物应用领域混编 Flutter 由于牵涉到原生植物网页与 Flutter 网页间转换,因此导航系统栈内可能会出现数个 Flutter 罐子的情况,即数个 Flutter 示例。Flutter 示例的调用成本非常高昂,每启动两个 Flutter 示例,就会创建两套捷伊渲染监督机制,即 Flutter Engine,以及底层的 Isolate。而这些示例间的内存是不互相共享的,会带来较大的系统资源消耗。

为的是解决混编工程建设中 Flutter 多示例的难题,业界有两种解决方案:

以今日头条为代表的修正 Flutter Engine 源码,使多 FlutterView 示例相关联的多 Flutter Engine 能够在底层共享 Isolate;以闲鱼为代表的共享 FlutterView,即由原生植物层驱动 Flutter 层渲染内容的方案。

不过,目前这两种解决方案都不够完美。所以,在 Flutter 官方支持多示例单发动机之前,应该尽量选用Flutter去合作开发一些闭环业务,减少原生植物网页与Flutter网页间的可视化,尽量避免Flutter网页重定向到原生植物网页,原生植物网页又启动两个捷伊Flutter实例的情况,并且保证应用领域内不要出现数个 Flutter 罐子示例的情况。

原文作者:xiangzhihong

原文链接:人类身份验证 – SegmentFault

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务