为什么写thrio?
在早期Flutter发布的时候,谷歌虽然提供了iOS和Android App上的Flutter嵌入方案,但主要针对的是纯Flutter的情形,混合开发支持的并不友好。
所谓的纯RN、纯weex应用的生命周期都不存在,所以也不会存在一个纯Flutter的App的生命周期,因为我们总是有需要复用现有模块。
所以我们需要一套足够完整的Flutter嵌入原生App的路由解决方案,所以我们自己造了个轮子 thrio ,现已开源,遵循MIT协议。
thrio的设计原则
- 原则一,dart端最小改动接入
- 原则二,原生端最小侵入
- 原则三,三端保持一致的API
thrio所有功能的设计,都会遵守这三个原则。下面会逐步对功能层面一步步展开进行说明,后面也会有原理性的解析。
thrio的页面路由
以dart中的 Navigator
为主要参照,提供以下路由能力:
- push,打开一个页面并放到路由栈顶
- pop,关闭路由栈顶的页面
- popTo,关闭到某一个页面
- remove,删除任意页面
Navigator中的API几乎都可以通过组合以上方法实现,replace
方法暂未提供。
不提供iOS中存在的 present
功能,因为会导致原生路由栈被覆盖,维护复杂度会非常高,如确实需要可以通过修改转场动画实现。
页面的索引
要路由,我们需要对页面建立索引,通常情况下,我们只需要给每个页面设定一个 url
就可以了,如果每个页面都只打开一次的话,不会有任何问题。但是当一个页面被打开多次之后,仅仅通过url是无法定位到明确的页面实例的,所以在 thrio
中我们增加了页面索引的概念,具体在API中都会以 index
来表示,同一个url第一个打开的页面的索引为 1
,之后同一个 url
的索引不断累加。
如此,唯一定位一个页面的方式为 url
+ index
,在dart中 route
的 name
就是由 '$url.$index'
组合而成。
很多时候,使用者不需要关注 index
,只有当需要定位到多开的 url
的页面中的某一个时才需要关注 index
。最简单获取 index
的方式为 push
方法的回调返回值。
页面的push
- dart 端打开页面
ThrioNavigator.push(url: 'flutter1');
// 传入参数
ThrioNavigator.push(url: 'native1', params: { '1': {'2': '3'}});
// 是否动画,目前在内嵌的dart页面中动画无法取消,原生iOS页面有效果
ThrioNavigator.push(url: 'native1', animated:true);
// 接收锁打开页面的关闭回调
ThrioNavigator.push(
url: 'biz2/flutter2',
params: {'1': {'2': '3'}},
poppedResult: (params) => ThrioLogger.v('biz2/flutter2 popped: $params'),
);
- iOS 端打开页面
[ThrioNavigator pushUrl:@"flutter1"];
// 接收所打开页面的关闭回调
[ThrioNavigator pushUrl:@"biz2/flutter2" poppedResult:^(id _Nonnull params) {
ThrioLogV(@"biz2/flutter2 popped: %@", params);
}];
- Android 端打开页面
ThrioNavigator.push(this, "biz1/flutter1",
mapOf("k1" to 1),
false,
poppedResult = {
Log.e("Thrio", "native1 popResult call params $it")
}
)
- 连续打开页面
- dart端只需要await push,就可以连续打开页面
- 原生端需要等待push的result回调返回才能打开第二个页面
- 获取所打开页面关闭后的回调参数
- 三端都可以通过闭包 poppedResult 来获取
页面的pop
- dart 端关闭顶层页面
// 默认动画开启
ThrioNavigator.pop();
// 不开启动画,原生和dart页面都生效
ThrioNavigator.pop(animated: false);
// 关闭当前页面,并传递参数给push这个页面的回调
ThrioNavigator.pop(params: 'popped flutter1'),
- iOS 端关闭顶层页面
// 默认动画开启
[ThrioNavigator pop];
// 关闭动画
[ThrioNavigator popAnimated:NO];
// 关闭当前页面,并传递参数给push这个页面的回调
[ThrioNavigator popParams:@{@"k1": @3}];
- Android 端关闭顶层页面