0%

启动优化

启动过程:

此处输入图片的描述

启动过程以main为界限,分为pre-main和main之后两部分

pre-main

加载dyld

动态库载入过程,会去装载app使用的动态库。而每一个动态库有它自己的依赖关系,会消耗时间去查找和读取。

rebase&binding

rebase:主要是调整镜像内部的指针,这里使用了ASLR(Address Space Layout Randomization 地址空间布局随机化)。程序每次启动后地址都会随机变化,这样程序里的所有代码地址都需要重新进行计算修复

binding:修复指向外部的指针。比如app中调用了NSLog函数打印信息,NSLog是系统函数,在程序开始运行的时候app是不知道NSLog函数指针是多少,此时就需要通过dyld_stub_binder技术找到NSLog指针地址进行调用。

Objc setup

runtime在此处初始化,对class和category进行注 册,selector唯一性判断

load&constructor&initialize

调用所有类的load的方法,初始化C&C++的静态化变量,然后调用 constructor 函数

main之后

main函数

创建整个app的autoreleasepool,初始化初始window,app界面开始展示

LifeCyle

指定rootviewcontroller,调用业务代码,完成各阶段业务

First Frame

main页面viewDidAppear 完成页面第一帧渲染。至此启动完成。

分析工具

pre-main阶段耗时分析:

在 Xcode 中 Edit scheme -> Run -> Auguments 将环境变量 DYLD_PRINT_STATISTICS 设为1

1
2
3
4
5
6
7
8
9
10
11
Total pre-main time: 1.2 seconds (100.0%)
dylib loading time: 297.95 milliseconds (23.5%)
rebase/binding time: 100.67 milliseconds (7.9%)
ObjC setup time: 110.68 milliseconds (8.7%)
initializer time: 758.19 milliseconds (59.8%)
slowest intializers :
libSystem.B.dylib : 6.71 milliseconds (0.5%)
libMainThreadChecker.dylib : 40.29 milliseconds (3.1%)
GPUToolsCore : 37.95 milliseconds (2.9%)
libglInterpose.dylib : 363.65 milliseconds (28.6%)
AiWayFashionCar : 471.71 milliseconds (37.2%)

如果将 Edit scheme -> Run > Auguments 将环境变量 DYLD_PRINT_STATISTICS_DETAILS 设为1,则可以更多详细的pre-main阶段的耗时:

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
total time: 2.1 seconds (100.0%)
total images loaded: 526 (508 from dyld shared cache)
total segments mapped: 66, into 8235 pages
total images loading time: 1.0 seconds (49.3%)
total load time in ObjC: 124.33 milliseconds (5.8%)
total debugger pause time: 753.19 milliseconds (35.7%)
total dtrace DOF registration time: 0.00 milliseconds (0.0%)
total rebase fixups: 830,184
total rebase fixups time: 95.24 milliseconds (4.5%)
total binding fixups: 851,403
total binding fixups time: 523.97 milliseconds (24.8%)
total weak binding fixups time: 3.85 milliseconds (0.1%)
total redo shared cached bindings time: 533.55 milliseconds (25.3%)
total bindings lazily fixed up: 0 of 0
total time in initializers and ObjC +load: 320.90 milliseconds (15.2%)
kscrash libSystem.B.dylib : 6.78 milliseconds (0.3%)
libBacktraceRecording.dylib : 6.98 milliseconds (0.3%)
libobjc.A.dylib : 2.52 milliseconds (0.1%)
libMainThreadChecker.dylib : 40.53 milliseconds (1.9%)
Flutter : 2.95 milliseconds (0.1%)
AiWayFashionCar : 396.86 milliseconds (18.8%)
total symbol trie searches: 1793354
total symbol table binary searches: 0
total images defining weak symbols: 63
total images using weak symbols: 143

备注:这里要跑低于ios 15.0的系统,才会在控制台打印

项目里用到的动态库:

通过命令 otool**-**L + 包路径查看使用了的动态库(包含系统库、嵌入的动态库):

1
otool -L /Users/mac/Desktop/Debugiphoneos/AiWayFashionCar.app/AiWayFashionCar

执行结果如下:

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
/usr/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.8)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1200.3.0)
/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
/usr/lib/libicucore.A.dylib (compatibility version 1.0.0, current version 68.2.0)
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 331.0.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
@rpath/ATAuthSDK_D.framework/ATAuthSDK_D (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AVFoundation.framework/AVFoundation (compatibility version 1.0.0, current version 2.0.0)
/System/Library/Frameworks/Accelerate.framework/Accelerate (compatibility version 1.0.0, current version 4.0.0)
/System/Library/Frameworks/AdSupport.framework/AdSupport (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AddressBook.framework/AddressBook (compatibility version 1.0.0, current version 1.0.0)
@rpath/App.framework/App (compatibility version 0.0.0, current version 0.0.0)
/System/Library/Frameworks/AssetsLibrary.framework/AssetsLibrary (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox (compatibility version 1.0.0, current version 1000.0.0)
/System/Library/Frameworks/CFNetwork.framework/CFNetwork (compatibility version 1.0.0, current version 1327.0.4)
/System/Library/Frameworks/Contacts.framework/Contacts (compatibility version 0.0.0, current version 3535.5.0)
/System/Library/Frameworks/CoreBluetooth.framework/CoreBluetooth (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1856.105.0)
/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics (compatibility version 64.0.0, current version 1557.3.2)
/System/Library/Frameworks/CoreLocation.framework/CoreLocation (compatibility version 1.0.0, current version 2665.0.10)
/System/Library/Frameworks/CoreMedia.framework/CoreMedia (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/CoreMotion.framework/CoreMotion (compatibility version 1.0.0, current version 2665.0.10)
/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony (compatibility version 1.0.0, current version 0.0.0)
/System/Library/Frameworks/CoreText.framework/CoreText (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/CoreVideo.framework/CoreVideo (compatibility version 1.2.0, current version 1.5.0)
/System/Library/Frameworks/EventKit.framework/EventKit (compatibility version 1.0.0, current version 1716.2.2)
@rpath/FMDB.framework/FMDB (compatibility version 1.0.0, current version 1.0.0)
@rpath/Flutter.framework/Flutter (compatibility version 0.0.0, current version 0.0.0)
/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1856.105.0)
/System/Library/Frameworks/GLKit.framework/GLKit (compatibility version 1.0.0, current version 126.0.0)
/System/Library/Frameworks/ImageIO.framework/ImageIO (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore (compatibility version 1.0.0, current version 612.3.6)
/System/Library/Frameworks/MapKit.framework/MapKit (compatibility version 1.0.0, current version 14.0.0)
/System/Library/Frameworks/MediaPlayer.framework/MediaPlayer (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices (compatibility version 1.0.0, current version 1141.1.0)
/System/Library/PrivateFrameworks/Network.framework/Network (compatibility version 1.0.0, current version 1.0.0, weak)
/System/Library/Frameworks/OpenGLES.framework/OpenGLES (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Photos.framework/Photos (compatibility version 1.0.0, current version 422.0.110)
/System/Library/Frameworks/QuartzCore.framework/QuartzCore (compatibility version 1.2.0, current version 1.11.0)
/System/Library/Frameworks/Security.framework/Security (compatibility version 1.0.0, current version 60157.60.19)
/System/Library/Frameworks/StoreKit.framework/StoreKit (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration (compatibility version 1.0.0, current version 1163.60.3)
/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 5205.0.101)
/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox (compatibility version 1.0.0, current version 1.0.0, weak)
/System/Library/Frameworks/WebKit.framework/WebKit (compatibility version 1.0.0, current version 612.3.6)
@rpath/flutter_boost.framework/flutter_boost (compatibility version 1.0.0, current version 1.0.0)
@rpath/path_provider.framework/path_provider (compatibility version 1.0.0, current version 1.0.0)
@rpath/shared_preferences.framework/shared_preferences (compatibility version 1.0.0, current version 1.0.0)
@rpath/sqflite.framework/sqflite (compatibility version 1.0.0, current version 1.0.0)
@rpath/video_player.framework/video_player (compatibility version 1.0.0, current version 1.0.0)
@rpath/wakelock.framework/wakelock (compatibility version 1.0.0, current version 1.0.0)
@rpath/webview_flutter.framework/webview_flutter (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AppTrackingTransparency.framework/AppTrackingTransparency (compatibility version 1.0.0, current version 1.0.0, weak)
/System/Library/Frameworks/UserNotifications.framework/UserNotifications (compatibility version 1.0.0, current version 1.0.0, weak)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.0.0)
/System/Library/Frameworks/AVKit.framework/AVKit (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AuthenticationServices.framework/AuthenticationServices (compatibility version 1.0.0, current version 612.3.6, weak)
/System/Library/Frameworks/CoreData.framework/CoreData (compatibility version 1.0.0, current version 1145.0.0)
/System/Library/Frameworks/CoreImage.framework/CoreImage (compatibility version 1.0.0, current version 5.0.0)
/System/Library/Frameworks/PhotosUI.framework/PhotosUI (compatibility version 1.0.0, current version 422.0.110)
/System/Library/Frameworks/QuickLook.framework/QuickLook (compatibility version 1.0.0, current version 849.1.0)
/usr/lib/libnetwork.dylib (compatibility version 1.0.0, current version 1.0.0, weak)
  • 这里以/System ,/usr开头的是系统动态库
  • 以@rpath开头的是嵌入动态库,如u3d,flutter及其依赖项使用了动态库

查找无用类、分类

代码覆盖率检测等

AppCode

基于LLVM插件检测重复代码或者未被使用的代码

GitHub - erduoniba/hdcoverage: iOS(swift&oc)自动注入代码覆盖率指令脚本,

查看项目里调了哪些load方法:

如果将 Edit scheme -> Run > Auguments 环境变量里加:OBJC_PRINT_LOAD_METHODS 设为YES

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
107
108
109
110
111
112
113
114
115
116
117
118
objc[11939]: LOAD: category 'NSObject(NSObject)' scheduled for +load
objc[11939]: LOAD: +[NSObject(NSObject) load]
objc[11939]: LOAD: class 'NSNotificationCenter' scheduled for +load
objc[11939]: LOAD: category 'NSObject(NSObject)' scheduled for +load
objc[11939]: LOAD: +[NSNotificationCenter load]
objc[11939]: LOAD: +[NSObject(NSObject) load]
objc[11939]: LOAD: class '_DKEventQuery' scheduled for +load
objc[11939]: LOAD: +[_DKEventQuery load]
objc[11939]: LOAD: class '__ARCLite__' scheduled for +load
objc[11939]: LOAD: +[__ARCLite__ load]
objc[11939]: LOAD: class '__ARCLite__' scheduled for +load
objc[11939]: LOAD: +[__ARCLite__ load]
objc[11939]: LOAD: class 'AiwaysTrack' scheduled for +load
objc[11939]: LOAD: class 'MBPoiSearchSession' scheduled for +load
objc[11939]: LOAD: class 'MBPoiSuggest' scheduled for +load
objc[11939]: LOAD: class 'MBReverseGeocoder' scheduled for +load
objc[11939]: LOAD: class 'YYAnimatedImageView' scheduled for +load
objc[11939]: LOAD: class '_AFURLSessionTaskSwizzling' scheduled for +load
objc[11939]: LOAD: class 'BSBacktraceLogger' scheduled for +load
objc[11939]: LOAD: class 'ZXAztecHighLevelEncoder' scheduled for +load
objc[11939]: LOAD: class 'ZXCode39Reader' scheduled for +load
objc[11939]: LOAD: class 'JPVideoPlayerCellProtocol_JPProtocolMethodContainer' scheduled for +load
objc[11939]: LOAD: class 'JPVideoPlayerDownloader' scheduled for +load
objc[11939]: LOAD: class 'JPVideoPlayerScrollViewProtocol_JPProtocolMethodContainer' scheduled for +load
objc[11939]: LOAD: class 'AWTimerUtil' scheduled for +load
objc[11939]: LOAD: class 'AWUrlSchemeManager' scheduled for +load
objc[11939]: LOAD: class 'AWUserProfileAddressViewController' scheduled for +load
objc[11939]: LOAD: class 'AWWKWebView' scheduled for +load
objc[11939]: LOAD: class 'YYTextKeyboardManager' scheduled for +load
objc[11939]: LOAD: class 'JCommonServiceController' scheduled for +load
objc[11939]: LOAD: class 'JPUSHReceivedPacketController' scheduled for +load
objc[11939]: LOAD: class 'JCORENetworkReachabilityManager' scheduled for +load
objc[11939]: LOAD: class 'JPUSHIntegrate' scheduled for +load
objc[11939]: LOAD: class 'MobClick' scheduled for +load
objc[11939]: LOAD: class 'UMConfigure' scheduled for +load
objc[11939]: LOAD: class 'MBMapView' scheduled for +load
objc[11939]: LOAD: class 'NBSRNLanuch' scheduled for +load
objc[11939]: LOAD: class 'NBSActionEditorVC' scheduled for +load
objc[11939]: LOAD: class 'NBSActionDefiner' scheduled for +load
objc[11939]: LOAD: class 'NBSCrashModule' scheduled for +load
objc[11939]: LOAD: class 'NBSExtensionController' scheduled for +load
objc[11939]: LOAD: category 'NSObject(StartTime)' scheduled for +load
objc[11939]: LOAD: category 'UIImage(WebPConfig)' scheduled for +load
objc[11939]: LOAD: category 'NSObject(LL_Utils)' scheduled for +load
objc[11939]: LOAD: category 'NSURLSession(LL_Swizzling)' scheduled for +load
objc[11939]: LOAD: category 'NSURLSessionConfiguration(LL_Swizzling)' scheduled for +load
objc[11939]: LOAD: category 'NSArray(SwizzlSafe)' scheduled for +load
objc[11939]: LOAD: category 'NSMutableArray(SwizzlSafe)' scheduled for +load
objc[11939]: LOAD: category 'NSDictionary(SwizzlSafe)' scheduled for +load
objc[11939]: LOAD: category 'NSMutableDictionary(SwizzlSafe)' scheduled for +load
objc[11939]: LOAD: category 'NSNull(SwizzSafe)' scheduled for +load
objc[11939]: LOAD: category 'NSString(SwizzlSafe)' scheduled for +load
objc[11939]: LOAD: category 'NSMutableString(SwizzlSafe)' scheduled for +load
objc[11939]: LOAD: category 'UIControl(AW)' scheduled for +load
objc[11939]: LOAD: category 'UIApplication(MemoryLeak)' scheduled for +load
objc[11939]: LOAD: category 'UINavigationController(MemoryLeak)' scheduled for +load
objc[11939]: LOAD: category 'UITouch(MemoryLeak)' scheduled for +load
objc[11939]: LOAD: category 'UIViewController(MemoryLeak)' scheduled for +load
objc[11939]: LOAD: category 'NSObject(JPInjecting)' scheduled for +load
objc[11939]: LOAD: category 'UITextView(RCSBackWord)' scheduled for +load
objc[11939]: LOAD: category 'UITabBarController(ShouldAutorotate)' scheduled for +load
objc[11939]: LOAD: category 'UIApplication(BaiduMobStatApplication)' scheduled for +load
objc[11939]: LOAD: category 'UICollectionViewLayout(MJRefresh)' scheduled for +load
objc[11939]: LOAD: category 'UIScrollView(MJExtension)' scheduled for +load
objc[11939]: LOAD: category 'NSObject(MJKeyValue)' scheduled for +load
objc[11939]: LOAD: +[AiwaysTrack load]
objc[11939]: LOAD: +[MBPoiSearchSession load]
objc[11939]: LOAD: +[MBPoiSuggest load]
objc[11939]: LOAD: +[MBReverseGeocoder load]
objc[11939]: LOAD: +[YYAnimatedImageView load]
objc[11939]: LOAD: +[_AFURLSessionTaskSwizzling load]
objc[11939]: LOAD: +[BSBacktraceLogger load]
objc[11939]: LOAD: +[ZXAztecHighLevelEncoder load]
objc[11939]: LOAD: +[ZXCode39Reader load]
objc[11939]: LOAD: +[JPVideoPlayerCellProtocol_JPProtocolMethodContainer load]
objc[11939]: LOAD: +[JPVideoPlayerDownloader load]
objc[11939]: LOAD: +[JPVideoPlayerScrollViewProtocol_JPProtocolMethodContainer load]
objc[11939]: LOAD: +[AWTimerUtil load]
objc[11939]: LOAD: +[AWUrlSchemeManager load]
objc[11939]: LOAD: +[AWUserProfileAddressViewController load]
objc[11939]: LOAD: +[AWWKWebView load]
objc[11939]: LOAD: +[YYTextKeyboardManager load]
objc[11939]: LOAD: +[JCommonServiceController load]
objc[11939]: LOAD: +[JPUSHReceivedPacketController load]
objc[11939]: LOAD: +[JCORENetworkReachabilityManager load]
objc[11939]: LOAD: +[JPUSHIntegrate load]
objc[11939]: LOAD: +[MobClick load]
objc[11939]: LOAD: +[UMConfigure load]
objc[11939]: LOAD: +[MBMapView load]
objc[11939]: LOAD: +[NBSRNLanuch load]
objc[11939]: LOAD: +[NBSActionEditorVC load]
objc[11939]: LOAD: +[NBSActionDefiner load]
objc[11939]: LOAD: +[NBSCrashModule load]
objc[11939]: LOAD: +[NBSExtensionController load]
objc[11939]: LOAD: +[NSObject(StartTime) load]
objc[11939]: LOAD: +[UIImage(WebPConfig) load]
objc[11939]: LOAD: +[NSObject(LL_Utils) load]
objc[11939]: LOAD: +[NSURLSession(LL_Swizzling) load]
objc[11939]: LOAD: +[NSURLSessionConfiguration(LL_Swizzling) load]
objc[11939]: LOAD: +[NSArray(SwizzlSafe) load]
objc[11939]: LOAD: +[NSMutableArray(SwizzlSafe) load]
objc[11939]: LOAD: +[NSDictionary(SwizzlSafe) load]
objc[11939]: LOAD: +[NSMutableDictionary(SwizzlSafe) load]
objc[11939]: LOAD: +[NSNull(SwizzSafe) load]
objc[11939]: LOAD: +[NSString(SwizzlSafe) load]
objc[11939]: LOAD: +[NSMutableString(SwizzlSafe) load]
objc[11939]: LOAD: +[UIControl(AW) load]
objc[11939]: LOAD: +[UIApplication(MemoryLeak) load]
objc[11939]: LOAD: +[UINavigationController(MemoryLeak) load]
objc[11939]: LOAD: +[UITouch(MemoryLeak) load]
objc[11939]: LOAD: +[UIViewController(MemoryLeak) load]
objc[11939]: LOAD: +[NSObject(JPInjecting) load]
objc[11939]: LOAD: +[UITextView(RCSBackWord) load]
objc[11939]: LOAD: +[UITabBarController(ShouldAutorotate) load]
objc[11939]: LOAD: +[UIApplication(BaiduMobStatApplication) load]
objc[11939]: LOAD: +[UICollectionViewLayout(MJRefresh) load]
objc[11939]: LOAD: +[UIScrollView(MJExtension) load]
objc[11939]: LOAD: +[NSObject(MJKeyValue) load]

缺页异常引起的耗时分析:

打开 Instruments , 选择 System Trace
优化前:
此处输入图片的描述
优化后:
此处输入图片的描述

main之后各阶段耗时分析:

此处输入图片的描述
结合

1
2
3
4
NSDate* tmpStartData = [NSDate date];    
//耗时函数    
double deltaTime = [[NSDate date] timeIntervalSinceDate:tmpStartData];
NSLog(@">>>>>>>>>>unity_launch_costTime = %f ms", deltaTime*1000);

优化思路

pre-main优化

二进制重排

为了能减少系统因缺页中断产生的 Page In 操作,我们需要做的就是把启动链路上所有用到的方法都排在连续的页上,这样系统在加载符号的时候就可以减少相应的内存页数量的访问,从而减少整个启动过程的耗时
二进制重排具体实现

动态库改造:

项目用到的嵌入动态库主要是U3d,Flutter及其依赖库

U3d库因为有要求必须得用动态库,故不作改造

这里只把flutter依赖库改造为静态库,思路是在flutter模块的podfile里添加:

1
2
3
4
5
6
7
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|   
config.build_settings['MACH_O_TYPE'] = 'staticlib'
    end
  end
end

Flutter的引入是通过构建脚本生成动态库,然后导入到私有库引用,故这里直接更改构建脚本
脚本更改:

1
2
3
4
5
6
sed -i '' '38a\
target.build_configurations.each do |config|\
config.build_settings['MACH_O_TYPE'] = 'staticlib'\
end\
' Podfile

需要安装gsed

1
2
brew install gnu-sed
alias sed='gsed'

load方法改造

从原则上来说,我们在开发过程中不应该使用 +load,针对 +load 方法的优化,主要是采用如下几种方案:

  • 删除不必要的代码;
  • +load中代码延迟到 main 之后子线程处理或者首页显示之后;
  • 业务代码接口懒加载;
  • 改为 initialize 中执行,针对 initialize 中处理需要注意的是分类 initialize 会覆盖主类 initialize 以及有子类后 initialize 执行多次的问题,需要使用 dispatch_once 来保证代码只执行一次;

删除无用代码

删减没有被调用或者已经废弃的方法

main后优化:

三方SDK

有些三方 SDK 的启动耗时很高,将第三方SDK延后或并发。

远程配置

一些远程配置,如社区详情页支持flutter和H5方式展示,通过开关来控制,城市列表信息等,改为并发请求

图片

用 Asset 管理图片而不是直接放在 bundle 里。

Asset 会在编译期做优化,让加载的时候更快。此外在 Asset 中加载图片是要比 Bundle 快的,因为 UIImage imageNamed 要遍历 Bundle 才能找到图。

高耗时方法

Flutter引擎初始化较为耗时,项目里用到的主要是二级页,故将它放在加载第一帧之后再初始化

首帧渲染

自动布局

自动布局改为frame布局方式,以提升布局性能

默认启动页

除了第一次装包会显示倒计时启动页,之后每次启动都会显示一个默认启动页,和该默认启动页并发展示的是最终要展示的社区首页,因为社区首页需要网络请求加载数据,之前的方案为了每次冷启后不先展示一片空白影响用户体验,故先展示一个1s的默认启动页.

这里把默认启动页去掉,对首页数据进行了缓存,初次装包后会对请求的数据进行缓存,之后启动会直接初始化社区首页,并从缓存加载数据

懒加载其它Tab页

启动只加载推荐页,发现页、口碑页、排行榜、活动页等,点击时候再加载

优化效果

阶段 优化耗时
动态库改造 90ms
二进制重排 270ms
load方法改造 160ms
main之后 1.3s

此处输入图片的描述