mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 19:30:29 +00:00
Add ASLayoutRangeModeLowMemory
This commit is contained in:
parent
de4e4db671
commit
bf822dee37
@ -167,7 +167,7 @@
|
|||||||
return (ASCollectionView *)[super view];
|
return (ASCollectionView *)[super view];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RangeControllerLoggingEnabled
|
#if ASRangeControllerLoggingEnabled
|
||||||
- (void)visibilityDidChange:(BOOL)isVisible
|
- (void)visibilityDidChange:(BOOL)isVisible
|
||||||
{
|
{
|
||||||
[super visibilityDidChange:isVisible];
|
[super visibilityDidChange:isVisible];
|
||||||
|
|||||||
@ -138,7 +138,7 @@
|
|||||||
return (ASTableView *)[super view];
|
return (ASTableView *)[super view];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RangeControllerLoggingEnabled
|
#if ASRangeControllerLoggingEnabled
|
||||||
- (void)visibilityDidChange:(BOOL)isVisible
|
- (void)visibilityDidChange:(BOOL)isVisible
|
||||||
{
|
{
|
||||||
[super visibilityDidChange:isVisible];
|
[super visibilityDidChange:isVisible];
|
||||||
|
|||||||
@ -51,6 +51,15 @@ extern BOOL ASRangeTuningParametersEqualToRangeTuningParameters(ASRangeTuningPar
|
|||||||
.trailingBufferScreenfuls = 2
|
.trailingBufferScreenfuls = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_tuningParameters[ASLayoutRangeModeLowMemory][ASLayoutRangeTypeDisplay] = {
|
||||||
|
.leadingBufferScreenfuls = 0,
|
||||||
|
.trailingBufferScreenfuls = 0
|
||||||
|
};
|
||||||
|
_tuningParameters[ASLayoutRangeModeLowMemory][ASLayoutRangeTypeFetchData] = {
|
||||||
|
.leadingBufferScreenfuls = 0,
|
||||||
|
.trailingBufferScreenfuls = 0
|
||||||
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,12 +20,20 @@ typedef NS_ENUM(NSUInteger, ASLayoutRangeMode) {
|
|||||||
* Range controller can automatically switch to full mode when conditions change.
|
* Range controller can automatically switch to full mode when conditions change.
|
||||||
*/
|
*/
|
||||||
ASLayoutRangeModeMinimum = 0,
|
ASLayoutRangeModeMinimum = 0,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normal/Full mode that a range controller uses to provide the best experience for end users.
|
* Normal/Full mode that a range controller uses to provide the best experience for end users.
|
||||||
* This mode is usually used for an active scroll view.
|
* This mode is usually used for an active scroll view.
|
||||||
* A range controller under this requires more resources compare to minimum mode.
|
* A range controller under this requires more resources compare to minimum mode.
|
||||||
*/
|
*/
|
||||||
ASLayoutRangeModeFull,
|
ASLayoutRangeModeFull,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Low Memory mode is used when a range controller should limit the amount of work it performs to 0.
|
||||||
|
* Thus, it discards most of the views/layers that are created and it is trying to save as much system
|
||||||
|
* resources as possible.
|
||||||
|
*/
|
||||||
|
ASLayoutRangeModeLowMemory,
|
||||||
ASLayoutRangeModeCount
|
ASLayoutRangeModeCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,8 @@
|
|||||||
#import <AsyncDisplayKit/ASLayoutController.h>
|
#import <AsyncDisplayKit/ASLayoutController.h>
|
||||||
#import <AsyncDisplayKit/ASLayoutRangeType.h>
|
#import <AsyncDisplayKit/ASLayoutRangeType.h>
|
||||||
|
|
||||||
#define RangeControllerLoggingEnabled 0
|
#define ASRangeControllerLoggingEnabled 0
|
||||||
|
#define ASRangeControllerAutomaticLowMemoryHandling 0
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#import "ASRangeController.h"
|
#import "ASRangeController.h"
|
||||||
|
|
||||||
#import "ASAssert.h"
|
#import "ASAssert.h"
|
||||||
|
#import "ASWeakSet.h"
|
||||||
#import "ASDisplayNodeExtras.h"
|
#import "ASDisplayNodeExtras.h"
|
||||||
#import "ASDisplayNodeInternal.h"
|
#import "ASDisplayNodeInternal.h"
|
||||||
#import "ASMultiDimensionalArrayUtils.h"
|
#import "ASMultiDimensionalArrayUtils.h"
|
||||||
@ -32,6 +33,29 @@
|
|||||||
|
|
||||||
@implementation ASRangeController
|
@implementation ASRangeController
|
||||||
|
|
||||||
|
#pragma mark - NSObject
|
||||||
|
|
||||||
|
+ (void)load {
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
[self registerLowMemoryNotification];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Class
|
||||||
|
|
||||||
|
+ (ASWeakSet *)rangeControllers
|
||||||
|
{
|
||||||
|
static ASWeakSet<ASRangeController *> *rangeController;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
rangeController = [[ASWeakSet alloc] init];
|
||||||
|
});
|
||||||
|
return rangeController;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Lifecycle
|
||||||
|
|
||||||
- (instancetype)init
|
- (instancetype)init
|
||||||
{
|
{
|
||||||
if (!(self = [super init])) {
|
if (!(self = [super init])) {
|
||||||
@ -42,6 +66,8 @@
|
|||||||
_currentRangeMode = ASLayoutRangeModeInvalid;
|
_currentRangeMode = ASLayoutRangeModeInvalid;
|
||||||
_didUpdateCurrentRange = NO;
|
_didUpdateCurrentRange = NO;
|
||||||
|
|
||||||
|
[[self.class rangeControllers] addObject:self];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +78,33 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - Low Memory Handling
|
||||||
|
|
||||||
|
+ (void)registerLowMemoryNotification
|
||||||
|
{
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(lowMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)lowMemoryWarning
|
||||||
|
{
|
||||||
|
#if ASRangeControllerAutomaticLowMemoryHandling
|
||||||
|
ASWeakSet *rangeControllers = [self rangeControllers];
|
||||||
|
for (ASRangeController *rangeController in rangeControllers) {
|
||||||
|
if (rangeController.dataSource == nil) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASInterfaceState interfaceState = [rangeController.dataSource interfaceStateForRangeController:rangeController];
|
||||||
|
if (ASInterfaceStateIncludesDisplay(interfaceState)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
[rangeController updateCurrentRangeWithMode:ASLayoutRangeModeLowMemory];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Core visible node range managment API
|
#pragma mark - Core visible node range managment API
|
||||||
|
|
||||||
+ (ASLayoutRangeMode)rangeModeForInterfaceState:(ASInterfaceState)interfaceState
|
+ (ASLayoutRangeMode)rangeModeForInterfaceState:(ASInterfaceState)interfaceState
|
||||||
@ -158,7 +211,9 @@
|
|||||||
|
|
||||||
ASRangeTuningParameters parametersDisplay = [_layoutController tuningParametersForRangeMode:rangeMode
|
ASRangeTuningParameters parametersDisplay = [_layoutController tuningParametersForRangeMode:rangeMode
|
||||||
rangeType:ASLayoutRangeTypeDisplay];
|
rangeType:ASLayoutRangeTypeDisplay];
|
||||||
if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersDisplay, ASRangeTuningParametersZero)) {
|
if (rangeMode == ASLayoutRangeModeLowMemory) {
|
||||||
|
displayIndexPaths = [NSSet set];
|
||||||
|
} else if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersDisplay, ASRangeTuningParametersZero)) {
|
||||||
displayIndexPaths = visibleIndexPaths;
|
displayIndexPaths = visibleIndexPaths;
|
||||||
} else if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersDisplay, parametersFetchData)) {
|
} else if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersDisplay, parametersFetchData)) {
|
||||||
displayIndexPaths = fetchDataIndexPaths;
|
displayIndexPaths = fetchDataIndexPaths;
|
||||||
@ -193,8 +248,8 @@
|
|||||||
// This can be done once there is an API to observe to (or be notified upon) interface state changes or pipeline enterings
|
// This can be done once there is an API to observe to (or be notified upon) interface state changes or pipeline enterings
|
||||||
[self registerForNotificationsForInterfaceStateIfNeeded:selfInterfaceState];
|
[self registerForNotificationsForInterfaceStateIfNeeded:selfInterfaceState];
|
||||||
|
|
||||||
#if RangeControllerLoggingEnabled
|
#if ASRangeControllerLoggingEnabled
|
||||||
NSMutableArray<NSIndexPath *> *modifiedIndexPaths = (RangeControllerLoggingEnabled ? [NSMutableArray array] : nil);
|
NSMutableArray<NSIndexPath *> *modifiedIndexPaths = (ASRangeControllerLoggingEnabled ? [NSMutableArray array] : nil);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (NSIndexPath *indexPath in allIndexPaths) {
|
for (NSIndexPath *indexPath in allIndexPaths) {
|
||||||
@ -217,13 +272,19 @@
|
|||||||
// instant we come onscreen. So, fetch data and display all of those things, but don't waste resources preloading yet.
|
// instant we come onscreen. So, fetch data and display all of those things, but don't waste resources preloading yet.
|
||||||
// We handle this as a separate case to minimize set operations for offscreen preloading, including containsObject:.
|
// We handle this as a separate case to minimize set operations for offscreen preloading, including containsObject:.
|
||||||
|
|
||||||
// Set Layout, Fetch Data, Display. DO NOT set Visible: even though these elements are in the visible range / "viewport",
|
|
||||||
// our overall container object is itself not visible yet. The moment it becomes visible, we will run the condition above.
|
|
||||||
if ([allCurrentIndexPaths containsObject:indexPath]) {
|
if ([allCurrentIndexPaths containsObject:indexPath]) {
|
||||||
|
// DO NOT set Visible: even though these elements are in the visible range / "viewport",
|
||||||
|
// our overall container object is itself not visible yet. The moment it becomes visible, we will run the condition above
|
||||||
|
|
||||||
|
// Set Layout, Fetch Data
|
||||||
|
interfaceState |= ASInterfaceStateFetchData;
|
||||||
|
|
||||||
|
if (rangeMode != ASLayoutRangeModeLowMemory) {
|
||||||
|
// Add Display.
|
||||||
// We might be looking at an indexPath that was previously in-range, but now we need to clear it.
|
// We might be looking at an indexPath that was previously in-range, but now we need to clear it.
|
||||||
// In that case we'll just set it back to MeasureLayout. Only set Display | FetchData if in allCurrentIndexPaths.
|
// In that case we'll just set it back to MeasureLayout. Only set Display | FetchData if in allCurrentIndexPaths.
|
||||||
interfaceState |= ASInterfaceStateDisplay;
|
interfaceState |= ASInterfaceStateDisplay;
|
||||||
interfaceState |= ASInterfaceStateFetchData;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +306,7 @@
|
|||||||
ASDisplayNodeAssert(node.hierarchyState & ASHierarchyStateRangeManaged, @"All nodes reaching this point should be range-managed, or interfaceState may be incorrectly reset.");
|
ASDisplayNodeAssert(node.hierarchyState & ASHierarchyStateRangeManaged, @"All nodes reaching this point should be range-managed, or interfaceState may be incorrectly reset.");
|
||||||
// Skip the many method calls of the recursive operation if the top level cell node already has the right interfaceState.
|
// Skip the many method calls of the recursive operation if the top level cell node already has the right interfaceState.
|
||||||
if (node.interfaceState != interfaceState) {
|
if (node.interfaceState != interfaceState) {
|
||||||
#if RangeControllerLoggingEnabled
|
#if ASRangeControllerLoggingEnabled
|
||||||
[modifiedIndexPaths addObject:indexPath];
|
[modifiedIndexPaths addObject:indexPath];
|
||||||
#endif
|
#endif
|
||||||
[node recursivelySetInterfaceState:interfaceState];
|
[node recursivelySetInterfaceState:interfaceState];
|
||||||
@ -261,7 +322,7 @@
|
|||||||
_rangeIsValid = YES;
|
_rangeIsValid = YES;
|
||||||
_queuedRangeUpdate = NO;
|
_queuedRangeUpdate = NO;
|
||||||
|
|
||||||
#if RangeControllerLoggingEnabled
|
#if ASRangeControllerLoggingEnabled
|
||||||
NSSet *visibleNodePathsSet = [NSSet setWithArray:visibleNodePaths];
|
NSSet *visibleNodePathsSet = [NSSet setWithArray:visibleNodePaths];
|
||||||
BOOL setsAreEqual = [visibleIndexPaths isEqualToSet:visibleNodePathsSet];
|
BOOL setsAreEqual = [visibleIndexPaths isEqualToSet:visibleNodePathsSet];
|
||||||
NSLog(@"visible sets are equal: %d", setsAreEqual);
|
NSLog(@"visible sets are equal: %d", setsAreEqual);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user