页面加载网络时长-1需求规划

[toc]

页面加载网络时长-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
{
"page_duration": 8000,
"api": {
"total_duration": {
"start": 1000,
"end": 5000,
"duration": 4000,
},
"apis": [
{
"url": "api1",
"start": 1000,
"end": 5000,
"duration": 4000,
},
{
"url": "api2",
"start": 1000,
"end": 5000,
"duration": 4000,
}
]
}
}

步骤:

步骤 问题
1 一个页面加载过程必须进行的所有网络请求有哪些 8 梳理页面接口,建立并管理【页面(含页面类型)–到–页面加载过程必须进行的所有网络请求】的关联表
请求与页面加载的绑定:请求是哪个页面哪次进入发起的 基于梳理的页面接口,在请求时候
请求接口的开始和结束的记录及网络库对该数据的对外提供处理
请求接口的开始和结束的日志记录及展示处理
页面请求管理器(UnfinishPageApiManager):计算一个页面加载过程执行完所有必须的网络请求的耗时 4
页面绘制所需请求耗时信息的管理(AllPageTimeManager)
页面绘制各耗时信息总管理器(事件间等待,总完成的上报时机优化) 8

1、梳理页面接口,建立【页面(含页面类型)–到–页面加载过程必须进行的所有网络请求】的关联表管理器(静态、变更时需自己更新维护)

①梳理优先处理的核心页面

1
2
3
4
5
6
7
8
9
10
// allneedPage_ApiManager.dart
class AllNeedPageApiManager {
static Map<String, dynamic> allNeedPageApiMaps =
{
"ContentHomePage": [api1, api2],
"ContentDetailPage": [api1, api2],
"MallHomePage": [api1, api2],
"MallDetailPage": [api1, api2],
};
}

增加Type,区分一个页面不同业务使用。如订单列表中,我送出的和我收到的,同属于一个页面。

却通过type

2、网络库接口中,

  • 请求是哪个页面哪次进入发起的:

    为请求创建页面key:每次进入页面,创建页面唯一key,避免等下网络请求时候,不晓得是哪个页面哪个进入发起的。

  • 记录请求进行表

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// unfinishPage_ApiManager.dart
class UnfinishPageApiManager {
// 所有页面的所有请求
static Map<String, dynamic> unfinishPageApiMaps = {};
// 示例
static Map<String, dynamic> unfinishPageApiMaps =
{
"ContentHomePage": [
{
apiUrl: api1,
apiStart: apiStart,
apiEnd: apiEnd,
},
{
apiUrl: api2,
apiStart: apiStart,
apiEnd: apiEnd,
}
],
"ContentDetailPage": [
{
apiUrl: api1,
apiStart: apiStart,
apiEnd: apiEnd,
},
{
apiUrl: api2,
apiStart: apiStart,
apiEnd: apiEnd,
}
],
};

// 页面请求开始
static void startApi({required String api, required String pageKey}) {
// 加锁🔐
// 获取指定页面已有的请求列表
List<Map<String, dynamic>> pageRequestingApiMaps = unfinishPageApiMaps[pageKey] ?? [];
// 添加新请求
Map<String, dynamic> newApiInfoMap = {
apiUrl: api,
apiStart: apiStart,
};
pageRequestingApiMaps.add(newApiInfoMap);
// 解锁🔐
}

// 页面请求结束
static void finishApi({required String api, required String pageKey}) {
// 加锁🔐
// 获取指定页面已有的请求列表,及其个数
List<Map<String, dynamic>> pageRequestingApiMaps = unfinishPageApiMaps[pageKey] ?? [];
// 找到此请求的开始信息,并补充上此请求的结束信息
for (Map<String, dynamic> item in pageRequestingApiMaps) {
item.addAll({"apiEnd": apiEnd});
}
int hasFinishCount = pageRequestingApiMaps.length;

// 获取指定页面原本应该有几个请求
List<Map<String, dynamic>> pageNeedApiMaps = PageApiManager.allNeedPageApiMaps[pageKey] ?? [];
int needCount = pageNeedApiMaps.length;

// 判断是否是最后一个请求,是的话上报本次页面的所有所需结束
if (hasFinishCount >= needCount) {
_notifyToPage(pageRequestingApiMaps);
}
// 解锁🔐
}

// 通知页面请求完成
static _notifyToPage(List<Map<String, dynamic>> pageRequestingApiMaps) {
int minStart;
int maxEnd;
for (Map<String, dynamic> item in pageRequestingApiMaps) {
int itemStart = item["apiStart"];
int itemEnd = item["apiEnd"];
if (minStart == null) {
minStart = itemStart;
} else {
minStart = min(minStart, itemStart);
}
if (maxEnd == null) {
maxEnd = itemEnd;
} else {
maxEnd = max(maxEnd, itemEnd);
}
}
if (minStart == null || maxEnd == null) {
debugPrint("发生错误了");
return;
}
int pageApiTotalDuration = maxEnd - minStart;
Map<String, dynamic> pageApiMap = {
"page_duration": pageApiTotalDuration,
"api": {
"total_duration": {
"start": 1000,
"end": 5000,
"duration": 4000,
},
"apis": pageRequestingApiMaps
}
}
eventBus.fire(PageFinishLoadRequest(pageApiMap: pageApiMap));
}
}

页面接收

1
2
3
4
5
6
7
8
9
10
class AllPageTimeManager {
pageRequestEvent = eventBus.on<PageFinishLoadRequest>().listen((event) {
Map<String, dynamic> pageApiMap = event.pageApiMap;
});


_uploadToSevice({required Map<String, dynamic> uploadPageInfo}) {

}
}

End