关于flutter:Flutter-混合开发基础

41次阅读

共计 4614 个字符,预计需要花费 12 分钟才能阅读完成。

引言

Flutter 作为 Google 开源的新一代跨平台、高性能 UI 框架,旨在帮忙开发者高效地构建出跨平台的、UI 与交互体验统一的精美利用,推出后始终倍受开发者的青眼。

当须要开发一个全新的利用时,咱们能够很不便地从零开始,齐全应用 Flutter 进行开发。但如果是针对一个现有的利用,须要引入 Flutter 技术,显然应用 Flutter 全副重写一遍是不事实的。侥幸的是,Flutter 很好地反对了以独立页面、甚至是 UI 片段的形式集成到现有的利用中,即所谓的混合开发模式。 本文次要从一个 Android 开发的视角,谈谈 Android 平台下,Flutter 的混合开发与构建。

Hello Flutter

置信当初应该很少会有挪动端开发者不晓得 Flutter,这里不再做过多介绍。对于这门技术,应用过的应该绝大多数都会说好;没用过的举荐尝试一下,跑个 Demo 体验体验,有可能它就是你须要学习和把握的最初一门新技术了。回过头来,Flutter 到底有什么独特的魅力让它能从一众技术中怀才不遇呢?总结一下,次要有以下几点:

  • 跨平台:能够做到一套代码完满适配 Android、iOS 平台,将来还会笼罩更多平台,大大节俭了开发人力与保护老本,同时领有杰出的跨端 UI 体现一致性。
  • 高效开发:SDK 提供了丰盛的 UI 组件,开箱即用;申明式的 UI 构建形式,大大减少出错率;Debug 模式提供热重载能力,可实时预览代码变更,不须要从新编译装置。
  • 高性能:采纳自建渲染引擎,独立于零碎并可独自优化;区别于 RN、WEEX,没有中间层转换的额定开销;Release 模式下代码编译为 AOT 指令,运行高效。

受害于以上的外围劣势,Flutter 推出后圈了很多挪动开发者的粉,各互联网大厂也纷纷将其作为一项根底技术进行钻研。在 Flutter 初期,其利用场景次要是从 0 构建一个全新 App,对混合开发的反对很不敌对。但作为一门跨平台的技术框架,到底还是须要依赖原生平台提供的诸多零碎能力,此外还有泛滥现存原生 App 蠢蠢欲动,因而在这个需要背景下,混合开发的反对与欠缺至今已倒退得越来越好,上面咱们就用一个简略的示例开始 Android 端的 Flutter 混合开发与构建之旅。

引入 Flutter 模块

要在一个已有的 Android Project 中应用 Flutter,须要引入一个 Flutter Module。在 Android Studio(须要确保 Flutter 插件曾经胜利装置并启用)中关上现有 Android 工程,通过应用 File > New > New Module… 菜单,咱们能够新创建一个 Flutter 模块或是导入一个内部的 Flutter 模块。

这里以最简略的 Android App 我的项目为例,导入 Flutter 模块。在 Flutter 模块导入胜利之后,原工程文件、构造都会产生一些变动,次要有:

  • settings.gradle 文件新增了以下内容。其实就是执行对应 Flutter 模块下 .android/include_flutter.groovy 脚本文件,该步骤会引入一个名为 Flutter 的 Android Library Module,同时还会引入 Flutter 模块所依赖的所有插件。
setBinding(new Binding([gradle: this])) 
evaluate(new File( 
    settingsDir.parentFile, 
    'flutter_module/.android/include_flutter.groovy' 
)) 
include ':flutter_module' 
project(':flutter_module').projectDir = new File('../flutter_module')
  • 我的项目构造变动,如下图所示:

在引入 Flutter 模块之前,我的项目中仅有 app 一个 Module;而在引入之后,能够看到除了原有的 app Module 外,Flutter Gradle 插件主动引入了额定几个子 Module:

  • flutter_module:指代要引入的指标 Flutter Module,不会 apply Android 相干的任何插件,次要是蕴含 Flutter 相干源码、资源、依赖等。
  • flutter:为 Flutter Gradle 插件引入的 Android Library Module;次要负责编译 flutter_module 及其依赖的第三方 Package、Plugin 的 Dart 代码,以及打包 Flutter 资源等。
  • device_info:为 Flutter Gradle 插件主动引入的 Flutter Android Plugin Library Module,这是因为一开始我在 flutter_module 的 pubspec.yaml 文件中增加了对 device_info 这个插件的依赖。Flutter Gradle 工具会将 flutter_module 依赖到的所有插件其 Android 平台侧的代码、资源作为一个 Library Module 引入到我的项目中一起参加构建。如果要查看 flutter_module 引入了哪些 Plugin,能够查看其对应目录下的 .flutter-plugins 与 .flutter-plugins-dependencies 文件,这两个文件是执行 flutter pub get 时生成的,记录了插件的本地文件目录、依赖信息等。

留神:一个工程不能蕴含多个 Flutter Module,最多只能引入一个,这是由 Flutter 的 Gradle 插件决定的。

应用 Flutter

实现 Flutter 模块的引入后,咱们再来看看如何应用 Flutter。

增加依赖

首先须要在 App 模块的 build.gradle 脚本文件中增加对 Flutter 工程的依赖,只有这样 Flutter 模块才会参加到整个利用的构建中来,咱们也才可能在 App 模块中调用到 Flutter 提供的 Java 层 API。如下所示:

dependencies {implementation project(':flutter') 
}

运行 Flutter 页面

咱们能够抉择应用 Activity、Fragment 或者 View 来承载 Flutter 的 UI,这里次要介绍后面两种形式,并假如 flutter_module 中曾经通过 runApp 办法渲染了一个 widget。

  • 运行 Flutter Activity。应用 io.flutter.embedding.android.FlutterActivity 类能够很不便的启动一个 Flutter Activity,当然咱们也能够继承它并扩大本人的逻辑。示例代码如下:
FlutterActivity 
  .withNewEngine() 
  .build(context) 
  .also {startActivity(it) }
  • 运行 Flutter Fragment。能够应用 FlutterFragmentActivity 或者 FlutterFragment 来增加 Flutter UI 片段:a. 应用 FlutterFragmentActivity 能够主动创立并增加一个 FlutterFragment;b. 手动创立 FlutterFragment 后增加到指标 Activity 中。示例代码如下:
val flutterFragment = FlutterFragment.withNewEngine() 
      .dartEntrypoint(getDartEntrypointFunctionName()) 
      .initialRoute(getInitialRoute()) 
      .appBundlePath(getAppBundlePath()) 
      .flutterShellArgs(FlutterShellArgs.fromIntent(intent)) 
      .handleDeeplinking(shouldHandleDeeplinking()) 
      .renderMode(renderMode) 
      .transparencyMode(transparencyMode) 
      .shouldAttachEngineToActivity(shouldAttachEngineToActivity()) 
      .build<FlutterFragment>() 
fragmentManager 
      .beginTransaction() 
      .add( 
           FRAGMENT_CONTAINER_ID, 
           flutterFragment, 
           TAG_FLUTTER_FRAGMENT 
          ) 
       .commit()
  • 平台层和 Flutter 层通信。不论是开发 Plugin 还是业务逻辑,平台层与 Flutter 层通信是必不可少的,为此就须要应用到 MethodChannel。平台层通过 MethodChannel 申请调用 Flutter 层 API 时,数据在通过打包编码后,通过 JNI、DartVM 传到 Flutter 层解码后应用;待后果计算实现后,又会从新打包编码,通过 DartVM、JNI 传回到 Native 层;同理,在 Flutter 层申请调用平台层的 API 时,数据处理是统一的,只是流转方向相同。通过这种形式,平台层与 Flutter 层就建设了一个双向的、异步的通信通道。在上面的示例代码中,Native 层应用 dev.flutter.example/counter 创立一个 MethodChannel,并设置 Handler 接管 Dart 的近程办法调用 incrementCounter,并调用 reportCounter 将后果回传。
channel = MethodChannel(flutterEngine.dartExecutor, "dev.flutter.example/counter") 
channel.setMethodCallHandler { call, _ -> 
     when (call.method) { 
         "incrementCounter" -> { 
              count++ 
              channel.invokeMethod("reportCounter", count) 
         } 
     } 
}

Dart 层应用雷同的名称创立 MethodChannel,并设置 Handler 解决回调后果,随后调用 incrementCounter 办法申请 counter。示例代码如下:

final _channel = MethodChannel('dev.flutter.example/counter'); 
_channel.setMethodCallHandler(_handleMessage); 
_channel.invokeMethod('incrementCounter'); 
 
Future<dynamic> _handleMessage(MethodCall call) async {if (call.method == 'reportCounter') { 
      _count = call.arguments as int; 
      notifyListeners();} 
  }

这里咱们是通过手动创立 MethodChannel 进行通信的,这在进行简略通信的场景是没问题的,但在通信接口 API 比较复杂的状况就不是很实用了。

一是繁琐,因为咱们须要手写大量的打包、拆包代码;二是容易出错。这个时候就轮到 Pigeon 大显神通了。Pigeon 是一个官网推出的代码生成工具,能够生成类型平安的双向通信 API 接口,具体能够参考官网的 Example,这里不再赘述。

Pigeon:网易云信官网。

更多技术干货,欢送关注【网易智企技术 +】微信公众号。

正文完
 0