Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

背景

此篇文章,主要针对想要在原有Native工程的基础上集成Flutter的需求,所提供的混编方案的探讨。

  1. 官方方案的优缺点

(1)优点:

不需要每次 Run 起来之后,先进行 同步flutter代码(组件化Flutter后,因为组件化后flutter代码已经变为framework,所以每次进来需要先热更新同步代码)
不需要单独搞一个组件进行集成,管理组件的版本,发布等。
(2)缺点:

会非常耦合工程,需要修改工程配置,添加 BUILD PHASE 调用 flutter 中 xcode_backend.sh 脚本 去编译 Flutter。
如果使用pod管理,那么还需修改xcconfig配置。
因为需要调用 Flutter 的编译脚本,所以这种方式集成后,团队内所有组员电脑和打包机,都必须安装Flutter环境才能编译成功。

  1. Flutter 组件化混编方案

(1)优点:

不需修改 原有 xcconfig 配置。
不需要添加 Run Script 脚本。
运行不需要依赖 Flutter 环境。
(2)缺点

需要单独管理一个 flutter私有索引库。
开发加载 Flutter 页面 首次需要热更新 进行刷新同步 Flutter 代码。
(3)混编方案 实现核心思想

通过查看 Flutter 编译脚本xcode_backend.sh 和 测试单独引入编译产物,发现其实 只要拥有 Flutter 的编译产物,项目就可以接入 Flutter 的功能。
所以说只要把Flutter编译好的产物,放在工程里,那么就无需配置每次调用 xcode_backend.sh 脚本,也无需强耦合Flutter环境,不需要所有组员安装Flutter环境,只需要有发布开发需求的同学进行安装即可。
这就是Flutter组件化的实现核心点。
(4)Flutter 核心编译产物

App.framework:dart业务源码相关文件,在 Debug 模式下就是一个很小的空壳,在 Release 模式下包含全部业务逻辑。
flutter_assets:Flutter依赖的静态资源,如字体,图片等。
Flutter.framework:Flutter库和引擎。
目录

Flutter组件化 - 混编方案
Flutter组件化 - 断点调试
Flutter组件化 - 发布更新
Flutter组件化 - 一些坑点
一、Flutter组件化 - 混编方案

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

  1. Git仓库存放 - 示例说明

主要分为3个仓库,分别存放Native项目、Flutter 工程源码、Flutter 编译产物私有pod库。

flutter 工程创建,使用 flutter create -t module my_flutter 命令

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

  1. 项目目录 - 示例

Flutter_iOS :iOS开发主项目。
flutter_library :Flutter 项目的开发源码。
FlutterSDK :Flutter 源码的编译产物,所构建的私有 pod 库。
Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

  1. 混编方案说明

根据 只要拥有 Flutter 的编译产物,项目就可以接入 Flutter 的功能 的核心思想,我们如果进行组件化Flutter混编,那么大概思路是:
有组件化环境 - 混编方案说明

(1)在 flutter 项目目录下,执行 flutter build ios 针对 Flutter 项目进行编译打包,生成 Flutter 编译产物。

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

Flutter 的产物分为两种模式,一个是 Debug 模式,采用 JIT(Just In Time)的方式,好处是可以支持热更新,方便调试,,但是性能比较慢。

另一种是 AOT(Ahead Of Time)release 模式,好处是性能比较好。

通过 flutter build ios --debug 可打包出 Debug 下的 Flutter 编译产物。

flutter build ios 命令依赖于 Flutter 生成的 Runner 工程,所以要确保 Runner 工程能够编译成功,这样才能生成 flutter 编译产物。如果遇到编译失败,可以检查下 bundle id 修改一下,使用自己的证书。如下图示例:

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

(2)针对编译产物,制作 Flutter SDK 私有库, podspec 指定 App.framework、engine、flutter_assets 路径。

podspec 有省略

Pod::Spec.new do |s|
s.name = "FlutterSDK"
s.vendored_frameworks = 'Framework/.framework', 'Framework/engine/.framework'
s.resources = 'Framework/flutter_assets'
end
(3)上传 Flutter SDK 私有库项目到云端私有pod索引库。(如何制作私有 pod 索引库,可搜索查看相关资料,这里不细说了)

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

(4)iOS 主项目指定 Podfile ,拉取云端Flutter私有库到本地。

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

没有组件化环境 - 混编方案说明

没有组件化环境的项目,并且不会建立私有索引库。
那么只有手动 执行 flutter build ios 命令后,将编译产物手动拖拽到iOS项目中。

  1. 最后效果

如下图,可以看到最终工程只引用了一个私有 pod 库。

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

总结

对 flutter 项目执行 flutter build ios 命令,生成编译产物。
针对编译产物,制作为私有 pod 库。
主工程通过 cocoapods 引入私有 pod 库。
二、Flutter 组件化 - 断点调试

因为是编译后的资源接入,我们还需要保证 Flutter 开发的同学可以正常调试。

目录

单独运行 Flutter 工程调试
同时调试 iOS 和 Flutter(不支持断点)
同时调试 iOS 和 Flutter(支持断点)
注意点:

确保,已经安装 Android Studio(用于打开 Flutter 工程)
确保,项目中依赖的 Flutter 打包出来的是 Debug 版本,Release 版本是无法热更新和调试的(使用 flutter build ios --debug 打包 debug 版本)

  1. 单独运行 Flutter 工程调试 (只适合和 Native 没有太多关联的工程,比较少用)

使用 Android Studio 打开 Flutter 工程目录

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

选择好真机或者模拟器,然后点击 Run 按钮

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

这样 Run 起来后,我们就可以在 Flutter 项目中打断点调试。这种方法 只适合和 Native 没有关联的工程,比较少用。

  1. 同时调试 iOS 和 Flutter(不支持Flutter断点的方式)

这种方法,需要先打开 Xcode 运行到 Flutter 页面,再进行附加 Flutter 端口号。

使用 Xcode 打开 iOS 项目,运行起 Flutter 页面。
Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

会发现会输出一行日志,其中有一个端口号我们记录下来,例如:
flutter: Observatory listening on http://127.0.0.1:60455/
然后 使用 Android Studio 打开 Flutter 项目(不点击运行),在 底部的 终端框中输入 flutter attach --debug-port=60455,端口号替换为xcode 日志输出的端口号。
Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

Gif 演示

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

总结

先打开 iOS 工程,运行起 Flutter 页面,得到一个日志输出的端口号。
然后 Android Studio 打开 Flutter 工程,在底部终端处输入 flutter attach --debug-port=日志输出端口号,然后附加成功即可。
注意点:附加成功后,在终端处,按小写 r 只会刷新有有修改的文件,按大写的 R 会全部刷新,如果使用组件化的话,每次进入 Flutter 页面,Android Studio 附加成功后,都要先按大写 R 全部刷新一次 同步到最新代码。否则还会显示旧的页面。

  1. 同时调试 iOS 和 Flutter(同时支持Flutter 和 Xcode断点的方式)

这种方法,需要先打开 Android Studio 选择 Attach Debugger to Android Process 等待 Flutter 页面连接,然后在 iOS 端,运行到 Flutter 页面,Android Studio 就会附加成功。

首先打开 Flutter 工程,直接点击 Attach Debugger to Android Process,然后会等待 Flutter 页面连接。
Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

然后运行 iOS 工程,进入 Flutter 页面。
然后就会发现 Android Studio 已经显示在 同步文件了(Syncing files to device 张大森的 iPhone...)
同步完成即连接成功。
Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

注意坑点

我们可以看到 闪电符号 Flutter Hot Reload 和 返回绿色符号 Flutter Hot Restart
Flutter Hot Reload 为局部刷新,比如某个文件有改动,才会同步刷新此页面。Flutter Hot Restart可以理解为全部刷新,在 Android Studio 面板上也有对应按钮,相应也有对应快捷键。
按照 Flutter 组件化的开发方式,我们首次附加连接成功后,一定要遵循一个步骤,先 点击 Flutter Hot Restart 进行全部刷新,再点击 Flutter Hot Reload 局部刷新。因为本人发现,如果最后一次刷新点击的是 Flutter Hot Restart 按钮,那么发现断点会不生效,只有点击 Flutter Hot Reload 后 触发的断点才会生效。
Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学
Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学
演示 Gif

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

打断点.gif
总结

Android Studio 打开 Flutter 工程 ,点击 Attach Debugger to Android Process
然后运行 Flutter 页面。
然后点击Flutter Hot Restart (同步最新 Flutter 代码),在点击 Flutter Hot Reload 确保断点能够生效。
三、Flutter组件化 - 发布更新

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学
发布大概流程

(1)对 Flutter 工程 执行 flutter build ios 或 flutter build ios --debug 生成编译产物。

(2)把编译产物复制移动到 Flutter 私有库目录下。

(3)打包 上传更新私有库内容。

(4)主工程拉取最新版本。

版本更新说明

开发期间:基本只用热更新进行开发代码。
发布版本:一般可在上线前进行发布,所以组件版本更新,用的比较少。
四、一些坑点

(1)FlutterViewController 不释放

Flutter 开发集合系列之优雅的 Flutter 组件化 混编方案大神必学

加载 Flutter 页面后,返回后,VC 不会释放。闲鱼有大神研究过这个问题,不过目前我们没有找到解决方案去释放 VC。
我们使用单例持有了 VC,只能做到不每次进行叠加内存,不重新创建。每次进入 Flutter 页面都先重置一下。

(1)不支持x86_64

可以用xcode跑下,生成App.framewok,然后 lipo 命令合并下。
我们目前不支持模拟器,这种方案没有进行测试。
其它

如果有更好的调试方法,坑点解决方法,混编方法,欢迎交流反馈下。
下一篇文章 (主要涉及到 Flutter 开发的一些知识)

教你 Flutter 如何与原生进行交互 待更新
最近有很多粉丝反映怎么学好java? java开发技术不是一两天就能学好的关键是你看怎么学 跟谁去学,俗话说的好师傅领进门,修行靠个人,这个不是短时间类所能完成的任务,有想法的上方关注,下方留言“学习”我教你!

原文地址:https://blog.51cto.com/14233733/2396103

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要讲解了“FlutterComponent动画的显和隐怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究...
这篇文章主要讲解了“flutter微信聊天输入框功能如何实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“f...
本篇内容介绍了“Flutter之Navigator的高级用法有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处...
这篇文章主要介绍“Flutter怎么使用Android原生播放器”,在日常操作中,相信很多人在Flutter怎么使用Android原生播放器问题上存在疑惑,小编查阅了各式资料,整...
Flutter开发的android端如何修改APP名称,logo,版本号,具体的操作步骤:修改APP名称找到文件:android\\app\\src\\main\\AndroidManifest.xml
Flutter路由管理初识路由概念一.路由管理1.1.Route1.2.MaterialPageRoute1.3.Navigator1.4.路由传值1.5 命名路由1.6.命名路由参数传递1.7.适配二、路由钩子三、onUnknownRoute四、结尾初识路由概念路由的概念由来已久,包括网络路由、后端路由,到现在广为流行的前端路由。无论路由的概念如何应用,它的核心是一个路由映射表。比如:名字 detail 映射到 DetailPage 页面等。有了这个映射表之后,我们就可以方便的根据名字来完成路由的转发
前提:针对Android开发者(windows系统下),已安装Git,AndroidStudio(建议4.0+版本)一.下载Flutter SDK地址:https://flutter.dev/docs/development/tools/sdk/releases,在 Stable channel (Windows)里面下最新版本即可。Flutter的渠道版本会不停变动,请以Flutter官网为准。在中国,要想正常获取安装包列表或下载安装包,可能需要翻墙,也可以去Flutter github项目下去下载安
一、变量变量是一个引用,根据Dart中“万物皆对象”原则,即变量存储的都是对象的引用,或者说它们都是指向对象。1.1.声明变量://1.不指定类型var name = 'aaa';//2.明确指定类型String name = 'aaa';因为有类型推导,所以两种实现效果一样,官方推荐在函数内的本地变量尽量使用var声明。在变量类型并不明确的情况下,可以使用dynamic关键字//3.使用dynamic关键字dynamic name = 'aaa';1.2.默认值未初始化的变量
前言Flutter2.0发布不久,对web的支持刚刚进入stable阶段。初学几天,构建web应用时候碰到一些问题,比如中文显示成乱码,然后加载图片出现图片跨域问题:Failed to load network image...Trying to load an image from another domain?1.开启web端构建:使用下面这个命令才可以开启Web端构建的支持flutter config --enable-web提示我们:重新启动编辑器,以便它们读取新设置。2.重
一.Flutter打Android release包的步骤:1.为项目创建一个.jks签名文件(很简单,跳过)2.创建一个文件key.properties,直接复制下面key.properties位置如图:在里面输入一下内容:storePassword=iflytekkeyPassword=iflytekkeyAlias=teachingmachinestoreFile=E:/teacher/app/keys/TeachingMachine.jks输入你自己的passwork以及
1 问题Android原生向js发消息,并且可以携带数据2 实现原理Android原生可以使用RCTEventEmitter来注册事件,然后这里需要指定事件的名字,然后在js那端进行监听同样事件的名字监听,就可以收到消息得到数据Android注册关键代码reactContext.getJSModule(DeviceEventManagerModule.RCT...
1 Flexbox布局1) flexDirection 可以决定布局的主轴,子元素是应该沿着水平轴(row)方向排列,还是沿着竖直轴(column)方向排列2) justifyContent 决定其子元素沿着次轴(与主轴垂直的轴,比如若主轴方向为row,则次轴方向为column)的排列方式 有flex-start、center、flex-end、space-around...
1 实现的功能在网上看React Native文档,我特码就想实现一个页面到另外一个页面的跳转,然后另外一个页面怎么获取参数,特么没找到一个说清楚的,要么太复杂,要么说了不理解,下面是我自己写的一个App.js文件,实现一个Home页面跳到另外Details页面,并且携带了参数怎么在Details页面获取,就是这么简单粗暴.2 测试DemoApp.js文件如下...
1 问题在一个文件构建一个对象,然后在另外一个文件里面new这个对象,通过构造方法传递参数,然后再获取这个参数2 测试代码Student.js文件如下'use strict';import React from 'react'import {NativeModules, NativeEventEmitter, DeviceEventEmitter,Ale...
1 简单部分代码export default class App extends Component<Props> { render() { return ( <View {styles.container}> <View {styles.welcome}> &l...
1 怎么实现发送和接收事件理论上封装了Android原生广播的代码,需要注册和反注册,这里用DeviceEventEmitter实现//增加监听DeviceEventEmitter.addListener//取消监听//this.emitter.remove();这里可也可以通过安卓原生向页面js发送消息,可以参考我的这篇博客React Native之Android原生通过Dev...
1、Component介绍一般Component需要被其它类进行继承,Component和Android一样,也有生命周期英文图片如下2 具体说明1)、挂载阶段constructor()//构造函数,声明之前先调用super(props)componentWillMount()//因为它发生在render()方法前,因此在该方法内同步设置状态...
1 触摸事件普通点击我们可以使用onPress方法,我们可以使用Touchable 系列控件设计我们的按钮TouchableHighlight 背景会在用户手指按下时变暗TouchableNativeFeedback用户手指按下时形成类似墨水涟漪的视觉效果TouchableOpacity指按下时降低按钮的透明度,而不会改变背景的颜色TouchableWithoutFeedbac...
1 问题部分代码如下class HomeScreen extends React.Component { render() { return ( <View {{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>Home Scre...
1 Props(属性)和State(状态)和简单样式简单使用App.js代码如下/** * Sample React Native App * https://github.com/facebook/react-native * * @format * @flow */import React, {Component} from 'react';import {Pla...