Flutter 混合开发新选择

·  阅读 4344

logo Faraday: github.com/gfaraday/g_…

话不多说,开始之前先看一组图


flutter -> nativenative->flutterflutter in tab
f2n.gifn2f.giftab.gif

一个全新的flutter混合开发框架, 用于解决在混合开发会遇到的各种问题。为什么不使用社区现有的(flutter_boostd_stackflutter_thrio )几个解决方案,而是选择自己再造轮子呢?在回答这个问题之前,我们先来看看一个合格的混合栈框架应该具备哪些基础能力

需求

互跳

一直说混合、混合,那混合的是什么呢?这里的混合是指路由栈的混合,即flutter页面可以自由跳转到native页面,native页面可以跳转到flutter页面。路由切换的过程中需要处理不同页面堆栈切换时的黑屏、白屏、闪屏问题,还需要支持自定义路由切换动画,支持不同类型页面间回调传参

入口

即将flutter页面作为整个app的入口页面。作为入口页面需要解决的问题主要是从启动图到flutter页面的切换动画问题。另外还需要处理从其他业务线中直接跳回主页的场景

tab

tab架构在app中非常常见,ios中有UITabViewController安卓中使用Fragment也可以轻易的实现tab布局。这里需要注意的是在需要支持多个flutter tab多个native tab混合的情况。同时还需要考虑从tab跳转到其他native或者flutter页面的情况

弹出层

app的模态页面必不可少,这种弹出页面逻辑一般都比较独立,很适合用flutter实现,所以也需要必要的支持。弹出层的核心在于混合栈需要支持flutter的容器背景透明,以及支持自定义弹出动画,或者禁用/启用原生动画

定位到任意页面

现在的app都越来越复杂,业务流程越来越长很容出现跨很多层级的页面跳转。因此支持跳转到任意定位的页面也显得极其重要

iOS navigation bar

这是一个ios特有的场景。flutter的容器viewController肯定是需要隐藏掉navigation bar的,但是容器的前一个页面或者后一个页面都有可能需要隐藏或者显示navigation bar所以混合堆栈最好也能把这个问题处理了

Android 物理返回键

对于Android物理返回键的处理在混合栈中比较特殊,flutter提供了原生的WillPopScope来处理这个问题。混合栈最好能完美兼容此widget,避免再去创造更多的概念来解决此问题

动画

混合栈中涉及到原生容器与flutter页面之间的跳转,如果不能很方便的自定义页面跳转动画看起来会有很大的割裂感。所以支持自定义转场动画,看起来也是刚需

与其他社区框架配合

flutter社区有很多优秀的框架比如路由管理框架fluro,状态管理providermobx等等,还有比如最近超火的getx。为了能使用这些优秀的社区框架,混合栈管理框架的api一定要设计的足够巧妙,同时在iOS和原生端的也有大量的第三方库可供我们选择。因此需要对原生的入侵尽可能的小

其他 (非必需)

  • 通知

打通flutter与native之间的通知壁垒

  • 网络

将flutter的网络请求代理到native实现

  • 原生通信

封装MethodChannel方便与原生通信

到这里上面那个问题的答案就显而易见了,现有的几个框架都不能完美的解决以上问题。因此我们设计开发了g_faraday来满足以上需求。接下来我们看看faraday的基础架构。

架构

要设计一个混合栈框架,第一个问题就是

单引擎 OR 多引擎

这个问题目前来看似乎已经没有讨论的价值了。相比于单引擎,多引擎方案的优点并不明显,而且内容占用略大。因此我们很容易确定了采用单引擎模式

下一个问题,混合框架必然会涉及到三端(ios,android,flutter),他们之间有很多相似但是不相同概念,包括但不限于页面,页面生命周期等等,我们以那一端的概念为主呢?

页面概念

集成混合框架以后,我们大部分的开发工作应该都聚焦在flutter层,因此肯定需要以flutter widget的概念为主,避免将UIViewControllerActivity及其生命周期相关的一些概念引入flutter

接下来我们看以下打开页面的操作

NativePage(N00) --> FlutterPage(F00) --> FlutterPage(F01) --> NativePage(N10) --> FlutterPage(F10) --> FlutterPage(F11) --> FlutterPage(F12)

此时我们直接套入flutter_boost的设计理念来看一下,如果我们严格看照boost的设计逻辑使用,那么native侧会分别为F00F01F10F11生成4个对应的容器, 这个时候我们可以看到对内存会有比较大的压力,而且如果这几个F页面如果有弹出的模态页面那么会和原生交互产生混乱。 因此我们从这个地方切入,我们不再为每一个F页面生成一个对应的容器。对于一组连续的F页面(比如 F00-F01, F10-F11-F12)只生成一个容器。这样对于上述场景我们只需要生成2个容器即可。

与容器交互

native容器有自己的返回逻辑(ios滑动返回,android物理返回键), 而由于我们每一个容器都有可能容纳N个flutter页面,因此我们必须根据相应的状态对容器的返回事件做出响应。为了能精确的管理每个页面,因此我们每个容器都为他赋予一个navigator,我们通过navigator的observer就可以精确的控制容器返回事件,具体逻辑如下:

  • iOS FaradayViewController

如果容器内有多于一个flutter页面,或者widget树中存在一个或者多个WillPopScope那么禁用容器本身的滑动返回手势,反之启用

  • Android FaradayActivity OR FaradayFragment

如果容器内有多于一个flutter页面,或者widget树中存在一个或者多个WillPopScope那么优先pop flutter page或者执行WillPopScope call, 反之直接pop容器

设计原则

从上面的基础架构可以看出我们的整体逻辑非常简单,因此我们最终实现出来的框架对三端的入侵都非常非常的小,尤其是flutter层,你甚至可以忘了faraday,一切就像开发纯flutter应用那样,使用第三方框架,处理路由,等等。。。

  • 对原有平台最小侵入
  • 对现有代码最小改动
  • API尽量保持和原有平台一致

总结

这里对faraday进行了一个粗略的介绍,具体内容大家可以移步github, 欢迎大家试用,反馈。欢迎各类 issue, pr

关于我们

我们是寓小二(长租公寓系统·创导者)技术团队,我们正在寻找志同道合的伙伴加入我们。

wechat

分类:
iOS
标签:
分类:
iOS
标签:
收藏成功!
已添加到「」, 点击更改