-
Notifications
You must be signed in to change notification settings - Fork 6k
[ios_platform_view] MaskView pool to reuse maskViews. #38989
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,8 @@ | |
|
||
- (instancetype)initWithFrame:(CGRect)frame screenScale:(CGFloat)screenScale; | ||
|
||
- (void)reset; | ||
|
||
// Adds a clip rect operation to the queue. | ||
// | ||
// The `clipSkRect` is transformed with the `matrix` before adding to the queue. | ||
|
@@ -47,6 +49,28 @@ | |
|
||
@end | ||
|
||
// A pool that provides |FlutterClippingMaskView|s. | ||
// | ||
// The pool has a capacity that can be set in the initializer. | ||
// When requesting a FlutterClippingMaskView, the pool will first try to reuse an available maskView | ||
// in the pool. If there are none available, a new FlutterClippingMaskView is constructed. If the | ||
// capacity is reached, the newly constructed FlutterClippingMaskView is not added to the pool. | ||
// | ||
// Call |recycleMaskViews| to mark all the FlutterClippingMaskViews in the pool available. | ||
@interface FlutterClippingMaskViewPool : NSObject | ||
|
||
// Initialize the pool with `capacity`. When the `capacity` is reached, a FlutterClippingMaskView is | ||
// constructed when requested, and it is not added to the pool. | ||
- (instancetype)initWithCapacity:(NSInteger)capacity; | ||
|
||
// Reuse a maskView from the pool, or allocate a new one. | ||
- (FlutterClippingMaskView*)getMaskViewWithFrame:(CGRect)frame; | ||
|
||
// Mark all the maskViews available. | ||
- (void)recycleMaskViews; | ||
|
||
@end | ||
|
||
// An object represents a blur filter. | ||
// | ||
// This object produces a `backdropFilterView`. | ||
|
@@ -268,6 +292,7 @@ class FlutterPlatformViewsController { | |
// Traverse the `mutators_stack` and return the number of clip operations. | ||
int CountClips(const MutatorsStack& mutators_stack); | ||
|
||
void ClipViewAddMaskView(UIView* clipView); | ||
// Applies the mutators in the mutators_stack to the UIView chain that was constructed by | ||
// `ReconstructClipViewsChain` | ||
// | ||
|
@@ -328,6 +353,7 @@ class FlutterPlatformViewsController { | |
fml::scoped_nsobject<FlutterMethodChannel> channel_; | ||
fml::scoped_nsobject<UIView> flutter_view_; | ||
fml::scoped_nsobject<UIViewController> flutter_view_controller_; | ||
fml::scoped_nsobject<FlutterClippingMaskViewPool> mask_view_pool_; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason to make this a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I should change it to properties. I was blindly following the current pattern. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, actually, it is in a c++ class. So I think scoped_nsobject is better that the lifecycle is automatically managed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Which class is c++? Your new There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FlutterPlatformViewsController is the c++ class. |
||
std::map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>> factories_; | ||
std::map<int64_t, fml::scoped_nsobject<NSObject<FlutterPlatformView>>> views_; | ||
std::map<int64_t, fml::scoped_nsobject<FlutterTouchInterceptingView>> touch_interceptors_; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -271,6 +271,10 @@ - (instancetype)initWithFrame:(CGRect)frame screenScale:(CGFloat)screenScale { | |
return self; | ||
} | ||
|
||
- (void)reset { | ||
paths_.clear(); | ||
} | ||
|
||
// In some scenarios, when we add this view as a maskView of the ChildClippingView, iOS added | ||
// this view as a subview of the ChildClippingView. | ||
// This results this view blocking touch events on the ChildClippingView. | ||
|
@@ -447,3 +451,64 @@ - (void)clipPath:(const SkPath&)path matrix:(const SkMatrix&)matrix { | |
} | ||
|
||
@end | ||
|
||
@interface FlutterClippingMaskViewPool () | ||
|
||
@property(assign, nonatomic) NSUInteger capacity; | ||
@property(retain, nonatomic) NSMutableArray<FlutterClippingMaskView*>* pool; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this retain the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well never mind, retaining it after the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will add a test for it! |
||
// The index points to the first available FlutterClippingMaskView in the `pool`. | ||
@property(assign, nonatomic) NSUInteger availableIndex; | ||
|
||
@end | ||
|
||
@implementation FlutterClippingMaskViewPool : NSObject | ||
|
||
- (instancetype)initWithCapacity:(NSInteger)capacity { | ||
if (self = [super init]) { | ||
_pool = [[NSMutableArray alloc] initWithCapacity:capacity]; | ||
_capacity = capacity; | ||
_availableIndex = 0; | ||
} | ||
return self; | ||
} | ||
|
||
- (FlutterClippingMaskView*)getMaskViewWithFrame:(CGRect)frame { | ||
FML_DCHECK(self.availableIndex <= self.capacity); | ||
FlutterClippingMaskView* maskView; | ||
if (self.availableIndex == self.capacity) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it looks like the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can probably just compare with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The capacity is a static limit set for the pool. My intention is to limit the memory used by the pool. For example, (it is probably not possible in real life), I don't want the pool to cache 20 views for the whole application session. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. gotcha. I mistakenly thought that this capacity increases like an NSMutableArray. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, yeah it could be confusing, I added a comment. |
||
// The pool is full, alloc a new one. | ||
maskView = | ||
[[[FlutterClippingMaskView alloc] initWithFrame:frame | ||
screenScale:[UIScreen mainScreen].scale] autorelease]; | ||
return maskView; | ||
} | ||
|
||
if (self.availableIndex >= self.pool.count) { | ||
// The pool doesn't have enough maskViews, alloc a new one and add to the pool. | ||
maskView = | ||
[[[FlutterClippingMaskView alloc] initWithFrame:frame | ||
screenScale:[UIScreen mainScreen].scale] autorelease]; | ||
[self.pool addObject:maskView]; | ||
FML_DCHECK(self.pool.count <= self.capacity); | ||
} else { | ||
// Reuse a maskView from the pool. | ||
maskView = [self.pool objectAtIndex:self.availableIndex]; | ||
maskView.frame = frame; | ||
[maskView reset]; | ||
} | ||
self.availableIndex++; | ||
return maskView; | ||
} | ||
|
||
- (void)recycleMaskViews { | ||
self.availableIndex = 0; | ||
} | ||
|
||
- (void)dealloc { | ||
[_pool release]; | ||
_pool = nil; | ||
|
||
[super dealloc]; | ||
} | ||
|
||
@end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
supernit:
ClipViewSetMaskView
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done