feature: Weex APM

This commit is contained in:
FantasticLBP
2025-12-30 21:07:15 +08:00
parent 1142064d28
commit 7ac7513900
158 changed files with 9880 additions and 280 deletions

View File

@@ -18,9 +18,149 @@ UIView 绘制流程。
当调用 UIView `[UIView setNeedsDisplay]` 方法时,系统会立刻调用其 Layer 的同名方法 `[view.layer setNeedsDisplay]` 方法,之后相当于给当前 Layer 打上一个脏标记,之后会在当前 RunLoop 快要结束的时候才会调用 Layer 的 `[CALayer display]` 方法。然后进入当前 UIView 真正的绘制流程中。
其次,会判断 CALayer 的代理,有没有实现 `displayLayer:` 方法,如果没有实现,则进入系统的绘制流程中;如果实现了,则可能是异步绘制或者自定义渲染的实现。
其次,会判断 CALayer 的代理,有没有实现 `displayLayer:` 方法
- 如果没有实现,则进入系统的绘制流程:比如:创建绘制上下文、调用 `drawInContext:`、生成内容并赋值给 `contents`
- 如果实现了,则可能是异步绘制或者自定义渲染的实现。是**代理自定义绘制的入口**。代理可以在这个方法里直接设置`layer.contents`(比如异步绘制生成 UIImage 后赋值给`contents`),完全接管 layer 的内容渲染
Demo1:
自定义 View不实现 `displayInContext` 方法
```objective-c
#import <UIKit/UIKit.h>
@interface CustomDrawView : UIView
@end
@implementation CustomDrawView
// 重写drawRect: —— 系统绘制流程的上层入口
- (void)drawRect:(CGRect)rect {
// 1. 系统自动创建绘制上下文,这里可以直接获取
CGContextRef context = UIGraphicsGetCurrentContext();
// 2. 绘制操作对应系统流程的「调用drawInContext:」阶段)
// 设置填充色为红色
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
// 绘制一个矩形
CGContextFillRect(context, CGRectMake(20, 20, 100, 100));
NSLog(@"执行drawRect: → 底层对应系统调用CALayer的drawInContext:");
}
// 关键:不实现 displayLayer: 代理方法
// - (void)displayLayer:(CALayer *)layer {} // 注释掉,模拟「未实现」场景
@end
```
在 ViewController 中使用
```objective-c
#import "ViewController.h"
#import "CustomDrawView.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
// 1. 创建自定义View并添加到界面
CustomDrawView *drawView = [[CustomDrawView alloc] initWithFrame:CGRectMake(50, 100, 150, 150)];
drawView.backgroundColor = [UIColor lightGrayColor]; // 浅灰色背景,方便区分绘制区域
[self.view addSubview:drawView];
// 2. 触发绘制打脏标记RunLoop阶段系统会执行layer.display
[drawView setNeedsDisplay];
}
@end
```
结果:屏幕上会显示「浅灰色背景 + 红色矩形」;控制台打印: `执行drawRect: → 底层对应系统调用CALayer的drawInContext:`
分析:
- `[drawView setNeedsDisplay]` → 内部调用 `layer.setNeedsDisplay`,给 layer 打 “脏标记”
- 当前 RunLoop 的 CATransaction 阶段,系统调用 `[layer display]`
- layer 检查代理CustomDrawView有没有实现代理方法 → 未实现`-(void)displayLayer:(CALayer *)layer`
- 系统**自动创建绘制上下文** → 调用 `[layer drawInContext:]`UIView 的`drawRect:`是对这个方法的封装,所以`drawRect:`被执行)
- 系统将绘制结果生成位图 → 赋值给 `layer.contents`
- 最终 layer 把`contents`内容渲染到屏幕
Demo2:
自定义 Layer实现 `displatLayer:` 代理方法的 Layer
```objective-c
#import <QuartzCore/QuartzCore.h>
@interface CustomLayer : CALayer
@end
@implementation CustomLayer
// 重写CALayer的drawInContext: —— 系统绘制流程的核心方法
- (void)drawInContext:(CGContextRef)ctx {
// 系统创建的上下文会传入这个方法
NSLog(@"系统调用drawInContext: → 进入核心绘制阶段");
// 绘制操作:画一个蓝色圆形
CGContextSetFillColorWithColor(ctx, [UIColor blueColor].CGColor);
CGContextFillEllipseInRect(ctx, CGRectMake(20, 20, 100, 100));
}
@end
```
在 VC 中使用
```objective-c
#import "ViewController.h"
#import "CustomLayer.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
// 1. 创建自定义Layer
CustomLayer *customLayer = [CustomLayer layer];
customLayer.frame = CGRectMake(50, 250, 150, 150);
customLayer.backgroundColor = [UIColor lightGrayColor].CGColor;
[self.view.layer addSublayer:customLayer];
// 2. 触发绘制(打脏标记)
[customLayer setNeedsDisplay];
}
@end
```
结果:屏幕上显示「浅灰色背景 + 蓝色圆形」;并且输出:`系统调用drawInContext: → 进入核心绘制阶段`
分析:
- 调用 CALayer 的 setNeedsDisplay 方法,内部会调用 display 方法
- 系统会将其 CALayer 打上 dirty 标记
- RunLoop 会在一次 loop 的末尾,提交 CATranscation。然后去绘制 layer 的 displayLayer 方法
- 判断没有实现 displayLayer 方法,然后自动创建渲染上下文。
- 然后调用 `drawInContext:(CGContextRef)ctx` ,方法的 ctx 参数就是系统自动创建的上下文对象
- 该方法内创建的渲染内容,最后会合成一张 bitmap最后交给 layer.contents 属性
- 屏幕渲染 contents 内容
Tips`[UIView setNeedsDisplay]` 之后并不会立马调用 `[view.layer setNeedsDisplay]` 方法。要么手动触发 `[view.layer setNeedsDisplay]` 要么,调用一下 `-(void)drawRect:(CGRect)rect` 方法(即使是空实现也没关系)。
下面来个 Demo 展示下简单的异步绘制一个 String。