混编事项说明

一、事项简述

混编

二、混编工程搭建

1、项目本身重构,实现原生混编前提—原生包Flutter

Flutter项目降级成模块,作为原生部分。

  • 抽离原生部分,Flutter项目降级成模块:原生项目外移,与Flutter项目同层。
  • 修改原生模块依赖配置文件Podfile,引入降级后的Flutter模块。

2、引擎处理

目的:混合栈引擎共享

方案一:使用flutter_boost

  • flutter_boost 接入

3、验证接入效果

3.1、验证跳转

三、混编下缓存数据共享

1、Flutter下的SharedPreferences

2、iOS下的UserDefaults

3、Android下的sharedPreferences

四、混编下的路由跳转

1、Flutter下的 fluro

2、iOS下的 CTMediator

3、Android下的 ARouter

1、原生路由实现

2、Flutter路由和原生路由的交互跳转

五、混编下的打包

1、混编下的打包环境变量的修改

六、生命周期修改

原因: Flutter 的 WidgetsBindingObserver RouteAware 失效,必须使用混编下(如FlutterBoost)的生命周期,很多业务需要重新修改确认。

七、混编下的图片资源共享

核心:各平台图片库的图片存储和获取位置自定义

1、Flutter下的 extended_image

2、iOS下的 SDWebImage

3、Android下的 glide

八、组件

1、网络数据共享

1、Flutter上的 dio

2、iOS上 Swift 的 AlamofireOC 的 AFNetworking

3、Android上的 OkHttp

Android主流网络请求开源库的对比(Android-Async-Http、Volley、OkHttp、Retrofit)

网络的重试、缓存

2、图片库

见上文《图片资源共享》部分

3、其他三方库

火山、buglgy、地图等 — 不用重新做

4、UI基础组件

5、开发工具

5.1、日志系统

自定义的监控系统

九、桥接—-Flutter方法

oc_bridging_header

End

账号管理

前言:主要账号

序号 分类 使用的功能 账号 登录方式 所有人 联系方式 是否独有
1 苹果开发者账号 iOS开发、发布 账号、密码
2 微信开放平台 微信登录、分享、支付
3 极光一键登录 一键登录验证(验证码在腾讯云)
4 百度地图 定位功能
5 Bugly 崩溃、卡顿
编号 场景 官网 key/id信息 注册的账号 续费时间 备注
1 app发布
2 微信登录 https://open.weixin.qq.com
3 Bugly https://bugly.qq.com/v2/ appid
iOS:xxx
Android:xxx
个人账号
4 百度地图 https://lbsyun.baidu.com iOS:xxx
Android:
个人账号
5 极光一键登录 https://www.jiguang.cn appkey
公司账号
6 xxx
7 xxxx
8 xxxx

苹果开发者证书

p12 证书文件 及 mobileprovision 描述文件的管理:见 《iOS证书

一、苹果开发者账号

苹果设备注册管理.md

1、苹果开发者设备

因苹果设备每年只能添加100台,且即使删除后也是当做一台设备。所以请真正有需要的用户才提交申请。

如需申请,请填写表:

序号 用户类型 姓名 udid 机型
1 开发者 Qian iPhone12 Pro
2 测试人员
3 产品人员
4 内测用户

附、udid获取方式

方式1、请自行使用浏览器进入蒲公英的一键获取udid工具

方式2、直接扫码获取

image-20230508153431432

二、Bugly

官网:https://bugly.qq.com/

姓名 Bugly 其他

Id获取方式如图:

image-20230508134738713

End

项目CodeReview

一、

1、非空、空值是否合理

2、类型定义是否合理 (字符串/枚举值)

3、方法是否统一(如数字字符串的小数位数保留、弹窗)

4、变量的位置定义是否合理,是否需要传递。局部变量,全局变量。

5、接口是否简化,接口参数是否过多(如跳转到聊天页)

6、必要注释是否缺失

7、代码实现顺序是否合理

参考文章

End

业务数据基类-卡片

一、内容卡片规范

1、内容卡片规范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[
{
"cardType": "content",
"contentCard": {

},
"userCard": {

},
"bannerCards": [

]
},
{
"cardType": "user",
"contentCard": {

},
"userCard": {

},
"bannerCards": [

]
},
{
"cardType": "banner",
"contentCard": {

},
"userCard": {

},
"bannerCards": [

]
}
]

2、需求1:长按卡片,弹出反馈列表。

分析:因为同一个卡片在不同业务页面,不一定都可以进行反馈,所以需要提前知道每个卡片在不同业务页面是否可以进行反馈,甚至是知道可以进行哪些反馈选项操作。

方案1:提前知道每个卡片在不同业务页面是否可以进行反馈。

后台数据返回

1
2
3
4
"canNegativeCardTypes": [
"mallHomePage#cardType_content",
"mallHomePage#cardType_user"
]

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
void longPressCard() {
var cardType = "content";
var position = "mallHomePage";
var flag = "$position#cardType_$cardType"
bool canNegative = canNegativeCardTypes.contains(flag);
if (!canNegative) {
return; // 不用相应
}

List<NegativeModel> negativeModels = await request(Url, {flag: flag});
showNegativeList(negativeModels);
}

方案2:提前知道每个卡片在不同业务页面可以进行哪些反馈选项操作。

后台数据返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
"negativeFeedbackConfig": {
"mallHomePage": {
"cardType_content": [
{
"image": "xxx.png",
"text": "不喜欢该内容",
"negativeId": 1
},
{
"image": "xxx.png",
"text": "不喜欢该作者",
"negativeId": 2
},
{
"image": "xxx.png",
"text": "举报",
"negativeId": 3
}
],
"cardType_user": [
{
"image": "xxx.png",
"text": "不喜欢该作者",
"negativeId": 2
},
{
"image": "xxx.png",
"text": "举报",
"negativeId": 3
}
],
}
}

代码实现

1
2
3
4
5
6
void longPressCard() {
var cardType = "content";
var position = "mallHomePage";
List<NegativeModel> negativeModels = negativeFeedbackConfig[$position][cardType_$cardType];
showNegativeList(negativeModels);
}

End

业务数据基类-消息

一、推送消息规范

推送模拟参考::《iOS进阶_推送模拟》

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"code": 0,
"message": "success",
"result": {
"msgType": 1,
"msgDes": "金豆消息(对msgType的描述)",
"msgData": {
"msgId": "1234567890",
"msgTitle": "金豆消息标题",
"msgContent": "金豆消息内容",
"msgImage": "http://www.baidu.com/xxx.jpg"
},
"msgOnTap": {
"action_type": "route",
"action_name": "发布内容",
"action_value": "appScheme://xxx"
}
}
}

msgOnTap:代表点击该按钮需要进行的操作。

点击规范请查看:《路由规范(含点击属性规范).md

二、聊天消息规范

建议与推送消息结构完全一致,至少与推送消息中的result一致。

End

设备相关

一、分辨率与尺寸

最新iPhone全机型分辨率和尺寸收录

手机机型 (iPhone) 屏幕尺寸 (inch) 逻辑分辨率 (pt) 设备分辨率 (px) 缩放因子 (Scale Factor)
3G(s) 3.5 320x480 320x480 @1x
4(s) 3.5 320x480 640x960 @2x
5(s/se) 4 320x568 640x1136 @2x
6(s)/7/8 4.7 375x667 750x1334 @2x
6(s)/7/8 Plus 5.5 414x736 1242x2208 @3x
X/Xs /11 Pro 5.8 375x812 1125x2436 @3x
Xr /11| 6.1 6.1 414x896 828×1792 @2x
Xs Max /11 Pro Max 6.5 414x896 1242×2688 @3x
12 mini 5.4 360x780 1080x2340 @3x
12/12 Pro 6.1 390x844 1170x2532 @3x
12 Pro Max 6.7 428x926 1284x2778 @3x
13 mini 5.4 360x780 1080x2340 @3x
13/13 Pro 6.1 390x844 1170x2532 @3x
13 Pro Max 6.7 428x926 1284x2778 @3x

iPhone X系列随着机型增多,屏幕尺寸也发生了改变,安全距离也不同。竖屏状态下有44、48、47等(可能还有其他数值);横竖屏切换时也不相同:横屏时左右的安全距离相同,由原来竖屏下底部安全距离34改为与顶部安全距离相同。即横屏时左右安全距离相同,都为竖屏下顶部安全距离。
适配方案:如果项目中带SceneDelegate文件可添加以下代码,不带该文件的项目可去除iOS13的判断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+ (UIEdgeInsets)getIphoneSafeInsets {
UIEdgeInsets safeInsets = UIEdgeInsetsMake(20, 0, 0, 0);
if (@available(iOS 11.0, *)) {
if (@available(iOS 13.0, *)) {
safeInsets = [UIApplication sharedApplication].windows.firstObject.safeAreaInsets;
}
else {
safeInsets = [[UIApplication sharedApplication] delegate].window.safeAreaInsets;
}
}

if (safeInsets.top < 20) {
safeInsets.top = 20;
}

return safeInsets;
}

iphone_device_height

1
2
3
4
5
6
7
let screenHeight = UIScreen.main.bounds.size.height
let statusBarHeight = UIApplication.shared.statusBarFrame.size.height
let navigationBarHeight = self.navigationController?.navigationBar.frame.size.height ?? 0
let tabbarHeight = self.tabBarController?.tabBar.frame.height ?? 0
let screenWidth = UIScreen.main.bounds.size.width
let iphoneX = screenWidth >= 375.0 && screenHeight >= 812.0
let bottomGuideHeight: CGFloat = iphoneX ? 34 : 0

End

APM选型-1调研

一、确定需求

APM(Application Performance Management)选型的主要目的是通过监控、分析和优化应用程序的性能和行为,提高应用程序的可靠性、可用性和响应速度,提高用户体验和满意度,从而提升业务价值和竞争力。

APM的选型对应到手机APP上,其目的和需求分别主要如下:

目的:提升手机APP的性能和用户体验,提高用户满意度,增强品牌竞争。

1、痛点/所需功能/期望

序号 影响/目的 所需功能
1 应用的稳定性/可用性 崩溃率、卡顿率/ANR率、错误率
2 应用的性能、用户体验 启动时间、页面加载时间

痛点典型场景:

  • 参考文章 听云

    请求分析场景

    在大多数情况下,网络耗时和可用性仍然是衡量用户体验质量的标准。

    • 过长的响应时间会极大的降低客户容忍度,关键支付接口可用性直接影响GMV(成交总额),在某些情况下超长的响应耗时往往是由于后端响应缓慢导致。
    • 用户使用过程中会因为网络阻塞或处于弱网环境导致各种各样的网络错误,且往往无法通过服务端日志收集,而且令运维人员头疼的网络错误,往往跟客户端环境有着密切的联系。

    用户感知分析场景

    数字化时代,随着业务规模地逐渐增大,应用承载的业务逻辑也越来越复杂,对应的性能问题也日益增多:应用崩溃、卡顿、网络延时、图片加载失败等等性能问题就如同附骨之疽难以去除,由性能带来的各种问题会直接影响业务成交率及品牌好感度。

    现有用户体验优化方案已经不再像过去那样简单地处理占比最高的崩溃和解决数量最多的错误,而是有针对性地优先修复最影响用户体验的Bug,以便提高用户留存。

    基调听云App通过监控应用启动、页面展现和用户操作三大核心场景,以业务视角综合分析应用使用过程中的「启动耗时」、「首屏加载」及「用户操作」指标,覆盖了应用的全生命周期,从而综合评估用户使用过程中的体验情况。

    更多内容,请查看原文链接。

image-20230606141855303

2、预算成本

不限定,以最后对比数据后,再做选择。

二、调研市场

了解市场上已有的产品和解决方案,分析其特点、优劣势和市场占有率等。

1、调研包含内容/考虑点

序号 考虑项/因素 内容 其他
1 包含的功能 ①必须/主要功能
②补充功能
2 后台数据 控制台数据呈现、维度
3 收费标准 免费功能、免费额度、免费门槛

2、调研产品列表

厂家 产品 官网 支持列表
字节 火山引擎
听云 听云-Flutter 基调听云SDK Flutter功能支持列表
腾讯 QAPM https://wetest.qq.com/products/QAPM
腾讯 RUM/APP
(Real User Monitoring,RUM)
腾讯云可观测平台 TCOP 下的
前端性能监控 RUM

3、调研包含内容/考虑点对比表

APM选型调研对比表

三、制定评估标准

将APM产品的功能清单转化为具体的评估指标,并根据用户需求和期望,给予不同指标不同的权重。例如,对于监控指标,可以考虑启动时间、页面加载时间、卡顿率、崩溃率等方面,对于诊断指标,可以考虑问题定位时间、错误率、准确性等方面。

序号 类型 功能【含Flutter上的支持】 影响/目的 需求程度(1-10)
1 监控指标 崩溃率 应用的稳定性/可用性 10
2 监控指标 卡顿率/ANR率、错误率 应用的稳定性/可用性 10
3 监控指标 启动时间 应用的性能、用户体验 10
4 监控指标 页面加载时间–平台支持 应用的性能、用户体验 10
5 监控指标 页面加载时间–自定义支持 应用的性能、用户体验 5

根据上述评估标准,我们将《火山引擎》和《听云》列入备选方案。

四、筛选备选方案、实地数据对比

根据评估标准,筛选出符合要求的备选方案,并进行初步比较和评估。

1、筛选方案,详见:APM选型-2备选筛选

2、筛选方案下的实地数据对比,详见:云雀:APM火山VS听云数据对比

五、选型决策和采购

六、跟踪和评估

End