Merge pull request #2815 from dreampiggy/feature_animated_clear_when_stop
Support to clear frame buffer or reset frame index when stopped for SDAnimatedImageView
This commit is contained in:
commit
491fefdd48
|
@ -58,6 +58,20 @@
|
|||
*/
|
||||
@property (nonatomic, assign) BOOL shouldIncrementalLoad;
|
||||
|
||||
/**
|
||||
Whether or not to clear the frame buffer cache when animation stopped. See `maxBufferSize`
|
||||
This is useful when you want to limit the memory usage during frequently visibility changes (such as image view inside a list view, then push and pop)
|
||||
Default is NO.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL clearBufferWhenStopped;
|
||||
|
||||
/**
|
||||
Whether or not to reset the current frame index when animation stopped.
|
||||
For some of use case, you may want to reset the frame index to 0 when stop, but some other want to keep the current frame index.
|
||||
Default is NO.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL resetFrameIndexWhenStopped;
|
||||
|
||||
#if SD_UIKIT
|
||||
/**
|
||||
You can specify a runloop mode to let it rendering.
|
||||
|
|
|
@ -149,21 +149,15 @@ static NSUInteger SDDeviceFreeMemory() {
|
|||
self.animatedImage = nil;
|
||||
self.totalFrameCount = 0;
|
||||
self.totalLoopCount = 0;
|
||||
self.currentFrame = nil;
|
||||
self.currentFrameIndex = 0;
|
||||
self.currentLoopCount = 0;
|
||||
self.currentTime = 0;
|
||||
self.bufferMiss = NO;
|
||||
// reset current state
|
||||
[self resetCurrentFrameIndex];
|
||||
self.shouldAnimate = NO;
|
||||
self.isProgressive = NO;
|
||||
self.maxBufferCount = 0;
|
||||
self.animatedImageScale = 1;
|
||||
[_fetchQueue cancelAllOperations];
|
||||
_fetchQueue = nil;
|
||||
SD_LOCK(self.lock);
|
||||
[_frameBuffer removeAllObjects];
|
||||
_frameBuffer = nil;
|
||||
SD_UNLOCK(self.lock);
|
||||
// clear buffer cache
|
||||
[self clearFrameBuffer];
|
||||
}
|
||||
|
||||
- (void)resetProgressiveImage
|
||||
|
@ -179,6 +173,22 @@ static NSUInteger SDDeviceFreeMemory() {
|
|||
// preserve buffer cache
|
||||
}
|
||||
|
||||
- (void)resetCurrentFrameIndex
|
||||
{
|
||||
self.currentFrame = nil;
|
||||
self.currentFrameIndex = 0;
|
||||
self.currentLoopCount = 0;
|
||||
self.currentTime = 0;
|
||||
self.bufferMiss = NO;
|
||||
}
|
||||
|
||||
- (void)clearFrameBuffer
|
||||
{
|
||||
SD_LOCK(self.lock);
|
||||
[_frameBuffer removeAllObjects];
|
||||
SD_UNLOCK(self.lock);
|
||||
}
|
||||
|
||||
#pragma mark - Accessors
|
||||
#pragma mark Public
|
||||
|
||||
|
@ -466,6 +476,12 @@ static NSUInteger SDDeviceFreeMemory() {
|
|||
#else
|
||||
_displayLink.paused = YES;
|
||||
#endif
|
||||
if (self.resetFrameIndexWhenStopped) {
|
||||
[self resetCurrentFrameIndex];
|
||||
}
|
||||
if (self.clearBufferWhenStopped) {
|
||||
[self clearFrameBuffer];
|
||||
}
|
||||
} else {
|
||||
#if SD_UIKIT
|
||||
[super stopAnimating];
|
||||
|
|
|
@ -16,6 +16,7 @@ static const NSUInteger kTestGIFFrameCount = 5; // local TestImage.gif loop coun
|
|||
@interface SDAnimatedImageView ()
|
||||
|
||||
@property (nonatomic, assign) BOOL isProgressive;
|
||||
@property (nonatomic, strong) NSMutableDictionary<NSNumber *, UIImage *> *frameBuffer;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -206,6 +207,7 @@ static const NSUInteger kTestGIFFrameCount = 5; // local TestImage.gif loop coun
|
|||
#else
|
||||
imageView.animates = NO;
|
||||
#endif
|
||||
[imageView removeFromSuperview];
|
||||
[expectation fulfill];
|
||||
}
|
||||
}];
|
||||
|
@ -298,6 +300,80 @@ static const NSUInteger kTestGIFFrameCount = 5; // local TestImage.gif loop coun
|
|||
[self waitForExpectationsWithCommonTimeout];
|
||||
}
|
||||
|
||||
- (void)test25AnimatedImageStopAnimatingNormal {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"test SDAnimatedImageView stopAnimating normal behavior"];
|
||||
|
||||
SDAnimatedImageView *imageView = [SDAnimatedImageView new];
|
||||
|
||||
#if SD_UIKIT
|
||||
[self.window addSubview:imageView];
|
||||
#else
|
||||
[self.window.contentView addSubview:imageView];
|
||||
#endif
|
||||
// This APNG duration is 2s
|
||||
SDAnimatedImage *image = [SDAnimatedImage imageWithData:[self testAPNGPData]];
|
||||
imageView.image = image;
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
// 0.5s is not finished, frame index should not be 0
|
||||
expect(imageView.frameBuffer.count).beGreaterThan(0);
|
||||
expect(imageView.currentFrameIndex).beGreaterThan(0);
|
||||
});
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
#if SD_UIKIT
|
||||
[imageView stopAnimating];
|
||||
#else
|
||||
imageView.animates = NO;
|
||||
#endif
|
||||
expect(imageView.frameBuffer.count).beGreaterThan(0);
|
||||
expect(imageView.currentFrameIndex).beGreaterThan(0);
|
||||
|
||||
[imageView removeFromSuperview];
|
||||
[expectation fulfill];
|
||||
});
|
||||
|
||||
[self waitForExpectationsWithCommonTimeout];
|
||||
}
|
||||
|
||||
- (void)test25AnimatedImageStopAnimatingClearBuffer {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"test SDAnimatedImageView stopAnimating clear buffer when stopped"];
|
||||
|
||||
SDAnimatedImageView *imageView = [SDAnimatedImageView new];
|
||||
imageView.clearBufferWhenStopped = YES;
|
||||
imageView.resetFrameIndexWhenStopped = YES;
|
||||
|
||||
#if SD_UIKIT
|
||||
[self.window addSubview:imageView];
|
||||
#else
|
||||
[self.window.contentView addSubview:imageView];
|
||||
#endif
|
||||
// This APNG duration is 2s
|
||||
SDAnimatedImage *image = [SDAnimatedImage imageWithData:[self testAPNGPData]];
|
||||
imageView.image = image;
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
// 0.5s is not finished, frame index should not be 0
|
||||
expect(imageView.frameBuffer.count).beGreaterThan(0);
|
||||
expect(imageView.currentFrameIndex).beGreaterThan(0);
|
||||
});
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
#if SD_UIKIT
|
||||
[imageView stopAnimating];
|
||||
#else
|
||||
imageView.animates = NO;
|
||||
#endif
|
||||
expect(imageView.frameBuffer.count).equal(0);
|
||||
expect(imageView.currentFrameIndex).equal(0);
|
||||
|
||||
[imageView removeFromSuperview];
|
||||
[expectation fulfill];
|
||||
});
|
||||
|
||||
[self waitForExpectationsWithCommonTimeout];
|
||||
}
|
||||
|
||||
#pragma mark - Helper
|
||||
- (UIWindow *)window {
|
||||
if (!_window) {
|
||||
|
|
Loading…
Reference in New Issue