如何无缝的将Flutter引入现有应用?


为什么写thrio?

在前期Flutter发布的时分,谷歌虽然供给了iOS和Android App上的Flutter嵌入计划,但首要针对的是纯Flutter的情形,混合开发支持的并不友好。

. e {谓的纯RN、纯weex使用的生命周期都不存在,所以也不会存在一个纯Flutter的App的生命周期,由于咱们总是有需求复用现有模块。

所以咱们需求一套足够完整的Flutter嵌入原生A; { & + 0 q k 2 $ppH b ] a G X * 9的路由处理计划,所以咱们自己造了个轮子 thrio ,现已开源,遵循MIT协议。

thrio的规划准F e H + k 8 N G

  • 准则一,dart端最g % s M k小改动接入
  • 准则二,原生端最小侵入
  • 准则三,三端保持一致的API

thrio一切9 S h = [功用的规划,都会遵守这三个准则。下面会逐渐对功用层面一步步翻开进行阐明,后面也会有原理性的解析。

thrio的页面路由

以dart中的 Navigator 为首要参照,供给以下路由才干:

  • pu/ W r 1 Y 1 9 t ]sh,翻开一个页面并放到路由栈顶
  • pop,封闭路由栈顶的页面
  • popTo,封闭到某一个页面
  • remove,删去恣意页面q ` H O Y D l 4 V

Navigatu 6 k 5or中的API简直都能够经过组合以上办法完成,replace 办法暂未供给。

不供给iOS中存在的 present 功用,由于会导致原生路由栈被掩盖,保护杂乱度会非常高,如3 ? + A确实需W + b l 7求能够经过修正转场动画完成。

页面的索引

要路由,咱们需求对页面树立索引,通常情况下q + L ,咱们只需求给每个页面设定一个 url 就能够了,假如9 * L x K每个页面都只翻开一次的话,不会有任K K } d N s何问题。但是当一个页面被翻开多次之后,只是经过url是无法定位到明确的页面实例的,所以在 thrio 中咱们增加了页面索引的概念,详细在API中都会以 index 来表示,同一个url第一个翻开的页面的索引为 1 ,之后同一个 url 的索引不断x , ? ) [累加。

如此,仅有定位Y j w c ` | G v一个页面的方法为 url + index,在dart中 routename 就是由 '$url.$index' 组合而成。

很多时分,使用者g – _ 1 Y 6 7 X ?不需求关注 index,只有当需$ ! 0 o E求定位到多开的 url 的页面中的某一个时才需求关注 index。最简单获取 index 的方法为 push 办法的回调回来值。

页面的push

  1. dart 端翻开页面
ThrioNavigatoi o k 2 ] mr.push(url: 'fl& R U T & 8u% _ n 8 ] j /tter1');
// 传入参数
ThrioNavigator.push(url: 'native1', params: { '1': {'2': '3'}});
// 是否o ] P, ? 6 | ] =画,现在/ g I在内嵌的dart页面中动画无法取消,原生iOS页面有作用
ThrioNavigator.push(url: 'native1', animated:true);
/c ; ( D r ( P/ 接纳锁翻开页面的封闭回调
ThrioNavigator.push(
url: 'biz2/flutter2',
params: {'A o o R1'w & C [ C !: {'2': '3'}},
poppedResult: (params) =&) ( / : U & D P Igt; ThrioLogger.v('biz2/flutter2 popped: $params'),
);
  1. iOS 端翻开页面
[ThrioNavigator pushUrl:@"flutter1"];
// 接纳所翻K U 2 W k X a开页面的封闭回调
[ThrioNavigator pushUrl:@"biz2/fluttj 9 } E v n } Ser2" poppedResult:^(id _Nonnull params) {
ThrioLogV(@"biz2/flutter2 popped: %C o Y E H@", params);
}];
  1. Android 端翻开页面
ThrioNavigator.push(this, "biz1/flutter1"B A s R g,
mapOf("k1" to 1),
false[ 6 5 o,2 C ? A K E ! #
poppedResult = {
Log.e("Thrio", "native1 popResult call params $it")
}
)
  1. 接连翻开页面
  • dart端只需求await push,就能够接连翻开页面
  • 原生端需求等候push的result回调回来才干翻开第二个页面
  1. 获取所翻开页面封闭后的回调参数
  • 三端都能够经过闭包 poppedResult 来获取

页面的pop

  1. dart 端封闭顶层页面
// 默许动画敞开
ThrioNavigator.pop();
// 不敞开动画,原生和dart页面都收效
ThrioNavigator.pop(animated: false);
// 封闭当g $ c u o时页面,并传递参数给push这个页面的回调
ThrioNavigator.pop(params: 'popped flutter1'),
  1. iOS 端封闭顶层页面
// 默许动画敞开
[ThrioNavigator pop];
// 封闭动画
[ThrioNavigator popAnimated:NO];
// 封闭当时页面,并传递参数给push这个页面的回调
[ThrioNavigator popParams:@{@"k1": @3}];
  1. Android 端封闭顶层页面
ThrioNavigator.pop(this, params, animated)

页面的popTo

  1. dart 端封闭到T e b g @ / t ]页面
// 默许动画敞开
ThrioNavigZ q d s o { q g ^ator.popTo(urr e R 1l: 'flutteq r M ! = - 4r1');
// 不敞开动画,原生和dart页面都收效
ThrioNavigator.popTo(url: 'flutter1', animated: false);
  1. iO6 S z j r DS 端封闭到页面
// 默许动画敞开
[ThrioN7 ; + ]avigator popToUrl:@"flutter1"];
// 封闭r p Tu W ; ) 8 =
[ThrioNavigator popToUrl:@"flutter1" animated:NO];
  1. Android 端封闭到页面
ThrioNavigator.popTo(context, url, index)

页面的remove

  1. dart 端封闭特定页面
ThrioNavigator.remove(url: 'flutte? 3 t er1');
// 只有当页面是顶层页面时,anX R i H } zimated参数才会收效
Thri_ w P @ * c % qoNav{ P _ ? T N xigator.remove(url: 'flutter1', animated: trut N f }e);
  1. iOS 端封闭特定页面
[ThrioNavigatorv g [ removeUra * rl:@"U 6 . %flutter1"];
//. * r Y c O M & f 只有当页面是顶层页面时,anim8 l (ated参数才会收效
[ThrioNavigator removeUrl:f : 6 + V D 2 e -@"flutter1" animated:NO];
  1. Androi1 [d 端封闭特定页面
Thy ; o 8 a D 2rioNavigator.remove% = 6(context, url, index)

thrio的| * !页面告诉

页面告诉一般来说并不在路由的领域之内,但咱们在实际开发中却经常需求使用到,由此发生的各种模块化框架一个比一个杂乱。S i g d f a

那么问题来了,这些模块化框架很难在三端互通,一切的这些模块化框架供给的才干无非最终是一个页面告诉的才干,并且页面告诉咱们能够非常简单的在三端打通。

鉴于此,页面告诉作为thrio的一个必备才干被引进了thrio。

发送页面告诉

  1. dart 端给特定页面发告诉
ThrioNavigator.notify(url: 'flutter1', name: 'reload');
  1. iOS 端给特定页面发告诉
[ThriN v 4 5 /oNavigator notifyUrl:@"flutter1" na- % j dme:@"reload"];
  1. Android 端给特定页面发0 ~ O ^ 4 G告诉
ThrioNavigator.notg }  ] r R  Kify(url, index, params)

接纳页面告诉

  1. dart 端接纳页面告诉

使用 NavigatorPageNN , - ) Q r ] _otify 这个 Widget 来完成在任何地方接纳当时页面收到的告诉。, ^ ] } x z

NavigatorPageNotify(
name9 7 x m f ; t: 'page1Notify',
onPageNotify: (params) =>
ThrioLogger.v('flutter1 rece5 E Y [ {ive notify: $params'),
child: Xxxx());
  1. iOS 端接纳页面告诉

UIw D _ A 1 ` # ~ AViewController完成协议NI E @avigatorPageNotifyProtocol,经过 onNot= I f x s difyi @ 来接纳页面告诉

- (void)onNotify:(NSString *)name params:(NSDictio6 f Z 4 @ d n ynary *)params {
Th^ o f F d =rioLogV(@"native1 onNok 2 Y Rtify: %@, %@", name, params);
}
  1. Android 端接纳1 $ [ ) Y页面告诉

Activity完成协议OnNotiZ b / q G i s q $fyListener,经过 onNotify 来接纳页面告诉

class Acth @ #ivity : A$ 0 DppCo[ [ t 3  2 0 @mpatActiI x s O q & Tvity(), OnNotifyListener {
ovt f S j 7erride fun onNotify(name: String, params: An- = - z v o I *y?) {
}
}

由于Android activity在后台或许6 V ; + G ^ X 3会被毁掉,所以页面告诉完成了一( 6 x Y o O r z K个懒呼应的行为,只有当页– ^ v面出现之后才会收到该告诉,这也符合页面需求改写的场景。

thrio的模块化

模块化在thrio里面只是一个非核心功用,只是为了完成准则二而引进原生端。

thrio的模块化才干由一个类供给,Thrio ] O ` H eoModule,很细巧,首要供给了 Module 的注册链和初始化链,让代码能够依据路由url进行文件分级分类。

注册链将一切模块串起来,字母块由最近的父V S ^ Z + * . d一级模块注册,新增模块的耦合度最低。

初始化链将一切模块需求初始化的代码串起来,相同是为了下降耦合度,在初始化链上能够就近注册模块的页面的结构n i t r K % Q a E器,页面路由调查者,页面生命周期调查者等,也能够在多引擎模式下提前发动某一个引擎。

模块间通信的才干由页面告诉完成。

mixin ThrioModule {
/// A functij 7 @on for registering a module, which will call
/// the `onModuleRegist6 z ? ] der` function of the `module`.
///
void registerModule(ThrioModu? j p r @ 9le moduT Y U K  l G c -le);
/// A function for module initialization that will call
/// the `onPageRegister`, `onModuleInit` and `onModuleAsyncIn1 v % ) j r U Lit`
/// methods of all modules.
///
void initModule();
/// A function for registering submodules.
///
void onModuleRegister() {}
/// A function for registering a page builder.
///
void onPageRegister() {}
/// A function for module initialization.
///
void onModuleIni. e = ?t() {}
/// A function for module asyc ; S Tnchronous initialil )  3 {zation.
///
void onModuleAsyncInit() {}
/// Regis` o P t U _ S / Iter J [ an page builder for the route? F + v ^r.
///
/. @ Y ` ] i m { 2// Unregistry by calling the return value `VoidCallback`.
///
VoidCallback registerPageBuilde{ v k V l { Or(String url, Navigator7 o z ; } 3PageBuilder builder);
/// Register observers for the life cycle of Dart pages.
///
/// UnregistrF ! 5 n Uy by calling the return value `VoidCallback`.
///
/// Do not override= Q M n ; Q # N this methodU t R w Q &.
///
Vox w MidCallback registerPageObserver(Nav6 ; N l ^ ! /igatorPageObserver pageObg y Qserver);
///G V H X y R W C L Register observers for route acti_ H i eon of Dart pages.
///
/// Unregistry by calling the return value& G 9 `VoidCallback`.
///
/// Do not override tr # } %his method.
///
VoidCallback reg3 0 g * ~ U U &isterRouteObserver(NavigatorRouteObserver routeObserver4 r 1 [ v ,);
}

thrio的页面生命周期

原生端能够获得一切页面的生命周期,Dart 端只能获取自身页面的生命周期

  1. dart 端获取页面的生命周期
class Modu6 S D ]le with ThrioModule, NavigatorPageObserver {
@override
void onPageRegister() {
regist# : v )  3 5erPn .  $ageObserver(this);
}
@override
void didI d {Appear(RouteSettings routeSettings) {}
@override
void didDisappef L h c i c d y kar(RouteSettings routeSettings) {}
@override
void onCreatY K i Z B p %e(RouteSettings routeSettings) {}
@override
void willApV 7 h } e Y Y _pear(RouteSett} e J - h 9 W i dings routeSettings) {}
@override
void willDisap8 * 3 8 K v + y Xpear(RouteSettings routeSettings) {}X ! x d N  Y
}
  1. iOS 端获取页面的生命周期
@interface Module1 : ThrioModule<NavigatorPageObserverProtocol>
@end
@implementation Module1
- (void)onPageRegister {Z g r }
[self registerPageObsera v bver:self]c V A;
}
- (void)onCreate:(Navigat4 w Q 5orRouteSettings *)routeSettings { }
- (void)willAppear:(NavigatorRouteSettings *)roh + H v y @ ? ;uteSettings { }
- (void)didAppear:(NavigatorRouteSettings *)rouK a xteL c O e A S * ^Setting0 4 8 2 ` K fs { }
- (void)willDisappeK ~ | m B r & G %ar:(NavigatorRouteSettings *)routeSettings { }
- (void)didDisappear:(NavigatorRouteSettings *)routeSettings { }l Q b A Z C |
@end

thrR * } X Q ( l *io的页面路由调查者

原生端能够调查一切页面的路由行为,dart 端只能调查 dart~ T ) { ^ } 0 页面的路由行为

  1. dart 端获取页面的路由行为
class Module with ThrioModule, Navigator& b # `RouteObserver {
@override
void onModuleRegit V k sster() {
registerRouteObserver(this);
}
@override
void didPop(
RouteSettingY c o 8 n = 1 5 8s routeSettings,
RouteSettings previousRouteSettings,
) {}
@P e C voverride
void didPopTo(
RouteSettings routeSettings,
RouteSetA P = / S *tings prA = [ J k weviousRouL e g { ~ fteSettings,
) {}
@override
void didPush(
RouteSettings routeSettings,
RouteSettings previousRouteSetti$ t ^ 1 Z } q  2ngs,
) {}
@overridb p i I C r ` E 3e
void didRemove(
RouteSettings routeSettings,
RouteSettings previousRoutF 5  3 C X i IeSettb + K o  G Qings,
) {}
}
  1. iOS 端获取页面的路由行为
@interface Module2 : ThrioModule<NavigatorRouteOb+ T 4 Q hserverH = CProtocol>
@end
@implementation Module2
- (void)onPageRegister {
[self registerRouteObserver:self];
}
- (void)didPop:(NavigatorRouteSettings *)routeSettings
previousRoute:(NavigU 4 V V r /atorRouteSettings * _Nullable)previ. E 6 %ousRouteSettings {
}
- (void)didPopTo7 g V C ` ! o:(NavigatorRouteSettings *)routeSettings
p0 s _reviousRoute:(NavigatorRouteSettings * _Nullable)previousRouteSettings {
}
- (void)didPush:(NavigatorRouteSettiN B o x qngs *)? c 0 c V o M #routeSettings
previousRoute:(NavigatorRouteSettings * _Nullable)previousRouteSetw S Gtings {
}
- (void)didRemove:(NavigatorRo5 ? ZuteSettings *H 7 c } X)routeSettings
previousRoute:(NavigatorRouteSettings * _. b ~ D . [ Z ; ]Nullable)previousRouteSettings {
}
@end

thrio的额定功用

iOS 显隐当时页面的导航栏

原生的导航栏在 dart 上一般情况下是不需求的,但0 z e / s = E k w切换到原生页面又需求把原生的导航O o k Z D n R t ,栏置回来,thrio 不供给的话,使用者较难扩展,我之前在R D l T ;现在一个干流的Flu| R v e m , E jtter接入库上进行s / d此项功用的扩展,很不流通,所以这个功用最好的r – n 1作用仍是 thrio 直接内置,切换到 dart 页面默许会隐z S m r藏原生的导航栏,切回原生页面也会自动恢复。另外也能够手动隐藏原生页面的导航栏。

viewController.thrio_hidesNavigatR z D QionBar = NOe 8 P;

支持页面封闭前弹窗承认的功用

假如用户正在填写一个表单,你或许经常会需求弹窗承认是否封闭; O @当时页面的功用。

在 darb J R a r 3 F e @t 中,有一个 Widget 供给了该功用,thrio 完好的保留了这个功用。

WillPopScope(
onWillPop: () async =&x J 4 ` p l -gt; true,
child: Coy n ; p p Rntainer(),
);

在 iOS 中C ! I – N @ },thrio 供给了相似的功用,回来 NO 表示不会封闭,一旦设置会将侧滑回来手势禁用

viewControllerr } 1.thrio_willPopBlock = ^(ThrioBoolCallback _Nonnull result) {
result7 A L O # ] D 7 i(NO);
};

关于 FlutterViewController 的侧滑回来手势,Flutter 默许支持的是| l s O &纯Flutter使用,仅支持单一的 FlutterViewControllerb ` ! 作为整个# } O W A l –App的容器,内部现已将 FlutterViewk i f N e I TController 的侧滑回来手势去掉。但 thrio 要处理的是 Flutter 与原生使用的无缝集成,所以必须将T n Y I [ (侧滑回来的手势加回来。

thrio的规划解析

现在开源 Flutter 嵌入原生的库,首要的仍是经过切换 FlutterEngine 上的原生容器来完成的,这是 Flutter 原本供给的原生容器之上最小改动而完成,需求当心处理好容器切换的时序,否则在页面导航时会发生崩溃。 w Q l根据 Flutter 供给的这个功用, thrio 构建了三端/ S ^ &一致的页面办理API。

dart 的核心类

dart 端只办理 dart页面

  1. 根据 RouteSettings 进行扩展,复用现有的字段
  • name = url.index
  • isIni* E Y stialRoute = !isNested
  • argumentsO g b 3 = params
  1. 根据 MaterialPageRoute 扩展的 NavigatorPageRoute
  • 首要供给页面描绘和转场动画的是否装备的功用
  1. 根据 Navigator 扩展,封装 NavigatorWidget,供给以下办法
  Future<bool> push(RouteSettings settings, {
b( X tool animated = true,
NaD V W uvigatorParam_ m )sCallback poppedResult,
});
Future<bool> pop(RoH / -uteSettings settings, {bool animated = true});
Future<bool> popTo(Rout@ r K w 4 z j QeSa / h q d pettings settin@ j w k Qgs, {bool animated = true})( n 4 E;
Future&lL W L Z ht;bool> remove(RouteSettings settings, {b 7 5 g $ . Sbool animg % D A , 0ated = false});
  1. 封装 ThrioNavigator 路由API
abstract class ThrioNavigator {
/// Push the page onto the navigation sh ` 8tack.
///
/// If a native p: F # I 8 7age builder exists for the `url`, open the native page,
/// othe! & g ]rwise op$ : S ; ! _ N ren the flutter page.
///
static Future<int> pv g y # u 6 uush({
@required String url,
params,
bool animateH o wd = true,
NavigatorParamsCallback poppedResult,
});a P 0 X U % ) h /
///r q h c H Send a] t z H noS ~ v X ` Jtification to the page.
///
/// Notifications will be triggered when the page enters the foregrW G . h s & 3ound.
/// Notifications with the same `name` will be overwritten2 / = Q X 6 L S.
/// 
static Future<bool> notify({
@required String url,
int index,
@required String name,
params,
});
/// Pop a page frog ; ~ y @ v Km the navigation stack.
///
static Future<bool> pop({params, bool animated = true})
static Future<bool> popTo({
@required String url,
int index,
bool animated = tru Z G g P ` =e,
});
/// RemoQ 3 U ? T B Ave the page with `url` in the navigation stack.
///N 1 P 2 C + #  
static Future<bool> remove({
@required String url,= Z v m
int index,
bool animated = true,
});
}

iOS 的核心类

  1. NavigatorRouteSettings 对应于 dart 的 RouteSettings 类,并供给相同数据结构

@interface NavigatorRouteSettings : NSObject
@7 W ^ s 3 Fproperty (nonatomic, copy, readonI d ` # g m R .ly) NSString *url;
@property (nonaA 8 X - 9 2 ? ? Ptomic, strong, readonl/ Q vy) NSNumber *index;
@property (nonV ( ) o p b Z Yatomic, assign, readonly) BOOL nested;
@property (nonatomi~ g X L ~ Jc, copy, readonly, nullable) id params;
@end
  1. NavigatorPageRoute 对应于 dart 的 NavigatorPageRoute
  • 存储告诉、页面m t 9 +封闭回调、NavigatorRouteSet^ B : n G {tings
  • route的双向链表
  1. 根据 UINavigationController 扩展,功用相似 dart 的 NavigatorWidget
  • 供给一些列的路由内部接口
  • 并能兼容非 thrio 系统内的页面
  1. 根据 UI- K ; 3 r y MViewController 扩展
  • 供给 Fly = e . Z H n .utterViewController 容器上的 dart( I q J F n 页面的办理功用
  • 供给 popDisable 等功用
  1. 封装 ThrioNavigator 路由API
@interfa! , 7  n  n =ce ThrioNavigator : NSObject
/// Push thO l # / - _ re page o= p _ @ o /nto the navigation stack.
///
///a i ? If a native page builder exists for the url, open the nJ & . S f t 9 F Native page,
/// otherwise open the flutte] X e P J ) ]r page.
///
+ (void)F ! H V w & tpushUrl:(NSString *)u, u 0 1rl
params:(id)params
animated:(BOOL)animated
result:(ThrioNumberCallback)result
poppedResult:: J 6 = #(ThrioIdCallback)poppedResult;
/// Send a notification to the page.
///
///@ % z Notifications will be triggered when the page enters the foreground.
/// Notifications with the same name will be overwritten.
///
+ (void)notifyUrl:(NSString *)url
index:(NSNumber *)index
name:(NSString *)name
params:(F K f e m X Eid)params
result:(Thri_ { 7 J ~ # Z 1oBoolCallback)result;
/// Pop a page from the navigation stack.
///
+ (void)popParams:(id)params
animated:(BOOL)a1 ; e C o znimated
result:(ThrioBoolCallback)result;
/// Pop the page in the navigation stack until th3 o k % . 4 ye page with `url`.
///
+ (void)popToUrl:(NSString *)url
index:(NSNumber *)index
animated:(BOOL)animated
result:(ThrioBoJ B nolCallback)result;
/// Remove the pag_ O + J @ pe with `url` in the navigation stack.
///
+ (void)removeUrl:(NSString *)url
index:(NSNumber *)index
animated:(BOOL)animated
result:(ThrioBoolCallback)result;
@end

dart 与 iOS 路由栈的结构

如何无缝的将Flutter引入现有应用?
  1. 一个使用允许发动多个FlutteC E 0 h [ E ar引擎,可让每个引擎运行的代码物理隔离,按需启用,下风是发动多个Flutter引擎或许导致资源耗费过多而引起问题;} 2 e
  2. 一个Flutter引擎经过切换能够匹配到多个FlutterViewConM w ! 5 | ! ? z !troller,这是Flutter高雅嵌入原生使用的前提条件
  3. 一个FlutterViewController能够内嵌多个D7 ) W @ { l / / Sart页面,有效减少单个FlutterViewController只翻开一个Dart页面导致的内存耗费过多问题,关于内存耗费的问题,后续会有说到。

dart 与 iOH 7 j ;S p1 # K | Z o ush的时序图

如何无缝的将Flutter引入现有应用?
  1. 一切路N g p ^ A ? T 由操作最终会聚于原生端开端,假如始于 dart 端,则经过 channel 调用@ r S h 4原生端的API
  2. 经过 url+index 定位到页面
  3. 假如页面是原生页面,则直接进行相关操作
  4. 假如页面是 Flutter 容器,则经过 channel 调用 dN + e . ;art 端对应的路由 API
  5. 接4步,假如 dart 端对应的路由 API 操作完成后回调,假如成功,– ! V T则履行原生端的路由栈同步,假如失利,则回调入口 API 的result
  6. 接4不,假如 dart 端对应的路由 API操作成功,则经过 route channel 调用T = n ` % :原生端对应的 route observer,经过 page channel 调用原生端对应的 page observer。

dart 与D A 7 d c l 2 iOS pop的时序图

如何无缝的将Flutter引入现有应用?
  1. pop 的流程与 push 根本一致;
  2. pop 需求考虑页面是否可封闭的问题;
  3. 但在 iOS 中,侧滑回来手势会导致问题, popViewControllerAnimao W O 2 P cted: 会在手势开端的时分调用,导致 dart 端的页面现已被 pod K c F K +p 掉,但假如手势被放弃了,则导致两端的页面栈不一致,thrio 现已处理了这个问题,详细流程稍杂乱,源码或许更好的阐明。

dart 与 iOS popK Z A ( OTo的时序图

如何无缝的将Flutter引入现有应用?
  1. popTo 的流程与 push 根本一致;
  2. 2 U q [ e在多引擎模式下,popTo需求处理多引擎的路由栈同步的问题;
  3. 另外在 Dart 端,popTo实际上是多个pop或者remove构成的,最终发生多次的didPop或didRemove行为,需求将多个pop或remove组合起来形成一个didPopTo行为。

da@ O w M u 4 V crt 与 iOS remove的时序图

如何无缝的将Flutter引入现有应用?
  1. remove 的流程与 pushM & B w 根本一致。

总结

现在 Flutter 接入原生使用干流的处理计划应该是boost,笔t x s z者的团队在项目深度使用过 boost,也积累了很多对 boost 改进的需求,遇到的最大问题是内存问题,每翻开一个 Fl , c i P ^ z – lutter 页面的内存开销根本到了很难接受的程度,thrio把处理内存问题作为头号任务,最终作用仍是不错的,比如以接连翻开 5 个 Flutter 页面计算,boost 的计划会耗费 91.60 t t h a K x7M 内存,thrio 只耗费 42.76 内存,模拟器上跑出来的数据大致如下:

demo 发动 页面 1 页面 2 页面 3 页面 4 页面 5
thrio 8.5Z o G c6 37.42 38.88 42.52 42.61 42.76
boost 6.81 36.08 50.96 66.18 78.86 91.67

相同接连翻开 5 个页面的场景,thrio 翻开第一个页面跟 boost 耗时是相同的,由于都需求翻开一个新的 Activity,之后 4 个页面 thrio 会直接翻开 Flutter 页面,耗时会降下来,以= @ 8 . # = m ,下单位为 ms:

demo 页面 1 页面 2 页面 3 页面 4 页面 5
thrio 242 45 39 31 37
boost 247 169 196 162 165

当然,th, d J E ~rio 跟 boost 的定位仍是不太相同的,thrio 更e P B B J ; – / a多的偏向于处理咱们业务上的需求,尽量做到开箱即用。

发表评论

提供最优质的资源集合

立即查看 了解详情