干货 | 携程火车票Flutter最佳实践

本文由携程火车票Flutter团队撰写,探讨了在已引入React Native的情况下选择Flutter的原因,主要关注性能优化。文章详细介绍了Provider在MVVM架构中的应用、性能调优方法,包括Flutter渲染原理、性能分析工具和实战技巧,以及Flutter布局和常见问题的解决方案。最后,文章总结了Flutter在复杂业务场景的优势,并展望了其未来发展。
摘要由CSDN通过智能技术生成

作者简介

 

本文为联合撰稿,作者为携程火车票Flutter团队,致力于跨端快速、高性能开发。

背景

在竞争激烈的移动时代,各大互联网公司都在争相抢夺市场,如何提高研发效率,快速迭代产品成为非常重要的因素。

跨平台方案能够节约一定开发、测试、运维成本。Flutter是由谷歌开源的跨平台框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。

一、 为什么选择Flutter

携程在已经引入了 React Native 的情况下,为什么还会选择 Flutter?更多是对性能的考虑。开发效率与性能体验就像天平两端,需要找到一个平衡点。RN 能够满足我们绝大部分的业务,并且热更、版本控制都很灵活。但是在复杂页面上,特别是在长列表的渲染上,还是存在一定的问题,促使我们去尝试一些新的解决方案。Flutter官宣自绘UI引擎,采用原生方式做渲染,媲美原生体验。

Native 、React Native、Flutter 对比如下:

1.1 研发效率

      

Flutter具有跨平台性,可以在多端上运行。同时Dart语言作为开发语言,本身的优势就在于它既支持JIT,又支持AOT,在 JIT(Just In Time)即时编译功能下,能提供 Hot Reload 功能。在开发过程中,实时地看到界面改动。生产包AOT编译,将代码编译成 ARM 二进制,从而既可以享受运行时又具有原生语言相近的运行效率。

1.2 扩展性好

Flutter提供了多种不同的Channel,用于 Dart 和平台之间相互通信。通过这些桥方法,使Flutter具有很好地与 Native 和 React Native 进行混合编程的能力。赋予 Flutter 一些 Native 的能力,同时也能很好地让我们在现有 Native 项目混合Flutter开发。 

二、 Provider对MVVM架构的实践

      

在Flutter的开发过程中,特别是一些业务复杂的页面,为了代码结构清晰,模块逻辑解耦,我们一般采用的是模块化的编程思想。随之而来的问题就是,组件之间怎么相互通讯,比如变更了登录态,如何通知其他模块刷新?

推荐使用Provider来管理各个组件的状态,我们实践下来 ,主体布局采用MVVM模式是比较方便做模块化编程的。

2.1 为什么需要使用Provider

如果状态是该组件私有的,则应该由组件自己管理;但是如果状态要跨组件共享,则该状态应该由各个组件共同的父元素来管理。对于组件私有的状态很好理解,当需要刷新当前widget的时候,只需要通过setState()的方法来实现组件重绘的效果;对于跨组件共享的状态,可以使用EventBus来实现。

可是当事件多了的时候,难以正确管理,其次订阅者必须要显式注册状态改变回调,也必须在组件销毁的时候手动解绑以避免内存泄漏。而Provider就可以通过自身的原理,简单地去实现状态共享,不需要麻烦的操作。且Provider是官方推荐的状态管理方式,具有良好的生态环境及维护团队。

2.2 Provider的实现原理

1)  InheritedWidget简单介绍

Provider是基于InheritedWidget的再次封装,InheritedWidget提供了一种数据在Widget树中自上而下传递,共享的方式。我们在根Widget继承了InheritedWidget,然后在该组件中存放一个数据data,那么可以在任意子Widget中来获取该组件的数据并使用。当在任一组件中改变了共享数据data,InheritedWidget组件会自上而下通知所有使用过共享数据的组件并刷新组件,同时会回调didChangeDependencies() 方法。

2)  Provider的原理和流程

共享数据的Model变化后,会自动通知ChangeNotifierProvider,ChangeNotifierProvider内部会重新构建InheritedWidget,而依赖该InheritedWidget的子Widget就会更新。

2.3 Provider的使用方式

架构模式图如下:

 

1)创建业务ViewModel,在ViewModel内部存放需要共享的数据。ViewModel 继承Flutter SDK中提供的ChangeNotifier类,它继承Listenable,也实现了一个Flutter风格的订阅者模式,其内部实现了addListener(),removeListener()等方法,实现对订阅者的处理。同时最好复写dispose()和notifyListeners()方法,防止用户在调用数据时销毁界面,而等到数据获取到以后通知界面刷新导致Crash。

2)注册状态管理类,使用ChangeNotifierProvider或者MutiProvider将需要共享数据的Widget包起来,单个NotifierProvider时使用ChangeNotifierProvider,多个NotifierProvider时使用MutiProvider包装,如下:

///多个NotifierProvider的时候return MultiProvider(providers: [    ChangeNotifierProvider(create: (context) => dataViewModel(mCommonAdvancedFilterRoot,query)),    ChangeNotifierProvider(create: (context) => UserPreferentialViewModel(query)),    ChangeNotifierProvider(create: (context) => UserPromotionViewModel())///需要调用共享数据的子Widget], child: ListResearchPageful(query));

3)在被包起来的Widget中的任一子组件中获取共享数据ViewModel,可以在StatefulWidget中的builder()方法中获取,也可以使用Builder组件进行获取,如下:

///在StatefulWidget中的build()方法中获取ViewModelclass ListResearchPageState extends TripState<ListResearchPageful> {@override  Widget build(BuildContext context) {///使用Provider包装以后,可以在widget的任一一个子widget获取共享数据并操作数据,在这里就是可以在HotelListView方法下的唯一位置获取ViewModel    var listViewModel = Provider.of<ListDataViewModel>(context);    var userPromotionViewModel = Provider.of<UserPromotionViewModel>(context);    return MediaQuery(        child: QueryListPage(widget.query,     ListDataViewModel, userPromotionViewModel));  }}
///借用Builder组件进行获取ViewModel@overrideWidget build(BuildContext context) {///
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值