So Iβve been thinking about ways to eliminate, or at least minimize, flashes caused by reloadData. This is one of the top complaints from developers that are new to the framework. I have a couple of solutions in mind and would love to start a discussion here:
Cell node prioritization:
Another way to solve this problem is hiding external components (esp. the underlying table/collection view) from the fact that reloadDatais broken down into a series of deletions and insertions. What it means is that, while making changes to the data set, we don't notify ASDataControllerDelegate at all. Then once we finished loading all cells, the delegate will be notified about a single atomic reload operation.
I believe either of these solutions can eliminate the flash. Although it will make developers less likely to do batch update :(
cc @Adlai-Holler @maicki @garrettmoon @appleguy
@nguyenhuy does @Adlai-Holler 's PR address this? Can it be closed?
@garrettmoon: it does partially address this issue. But I'm having an improvement in mind, will report back this week.
@nguyenhuy - could you update this thread? I know you've been working on improvements in this area. :)
i don't think flashes are gone. i create a simple table node with a cell containing just a image node and text node. If i call [tableNode reloadData], sometimes there is no flash, but for half of the time flash happens. I am at the latest commit of branch master.
@shellhue Are you seeing flashes at the image and text nodes level? Could you please post a video? There is a chance that we're talking about different kinds of flashes here :)
asyncdisplaykitflash.mov.zip
i have uploaded the demo video.
the view controller code is very simple.
#import "ViewController.h"
#import "BLCellNode.h"
@interface ViewController () <ASTableDelegate, ASTableDataSource>
@property (nonatomic, strong) ASTableNode *tableNode;
@end
@implementation ViewController
- (instancetype)init {
self = [super initWithNode:[ASDisplayNode new]];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
self.tableNode = ({
ASTableNode *node = [ASTableNode new];
node.delegate = self;
node.dataSource = self;
node;
});
[self.node addSubnode:self.tableNode];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.tableNode.frame = self.view.bounds;
}
- (void)refresh {
[self.tableNode reloadData];
}
- (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section {
return 2;
}
- (ASCellNode *)tableNode:(ASTableNode *)tableNode nodeForRowAtIndexPath:(NSIndexPath *)indexPath {
return [BLCellNode new];
}
@end
BLCellNode is as below:
#import "BLCellNode.h"
@interface BLCellNode ()
@property (nonatomic, strong) ASImageNode *imageNode;
@property (nonatomic, strong) ASTextNode *textNode;
@end
@implementation BLCellNode
- (instancetype)init {
self = [super init];
if (self) {
self.imageNode = [ASImageNode new];
self.imageNode.image = [UIImage imageNamed:@"sample"];
self.imageNode.style.height = ASDimensionMake(300);
[self addSubnode:self.imageNode];
self.textNode = [ASTextNode new];
NSDictionary *attributes = @{
NSFontAttributeName: [UIFont systemFontOfSize:16]
};
self.textNode.attributedText = [[NSAttributedString alloc] initWithString:@"η«ε»εε€ζθ¨η²ηΊ’θ²ε¦ηι£ζ―εΌε
°ε
ζε ζ€θ€θεΈηιε’θ¨ε‘η»δ»£ι£εθεΈηεε€εΌε
°ε
ηζθ‘ζ€η²δΊζ·±ε»ηη«ε»εε€ζθ¨η²ηΊ’θ²ε¦ηι£ζ―εΌε
°ε
ζε ζ€θ€θεΈηιε’θ¨ε‘η»δ»£ι£εθεΈηεε€εΌε
°ε
ηζθ‘ζ€η²δΊζ·±ε»ηη«ε»εε€ζθ¨η²ηΊ’θ²ε¦ηι£ζ―εΌε
°ε
ζε ζ€θ€θεΈηιε’θ¨ε‘η»δ»£ι£εθεΈηεε€εΌε
°ε
ηζθ‘ζ€η²δΊζ·±ε»ηη«ε»εε€ζθ¨η²ηΊ’θ²ε¦ηι£ζ―εΌε
°ε
ζε ζ€θ€θεΈηιε’θ¨ε‘η»δ»£ι£εθεΈηεε€εΌε
°ε
ηζθ‘ζ€η²δΊζ·±ε»η" attributes:attributes];
[self addSubnode:self.textNode];
}
return self;
}
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize {
return [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical spacing:10 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsCenter children:@[self.imageNode, self.textNode]];
}
@end
@shellhue I think the cells flash because they are asynchronously displayed and so for a short time their contents are not ready yet. Try setting neverShowPlaceholders to YES on the cell nodes. More information can be found here.
Yeah, you are right, after setting neverShowPlaceholders to YES, the flashes are gone. Our team uses AsyncDisplayKit heavily, but this kind of flash makes us limit the use, especially when there is a lot of refresh. Thanks very much.
@shellhue You're welcome! I'm glad to hear that you're unblocked! Feel free to join our Slack channel for even faster Q&A!
Most helpful comment
@shellhue I think the cells flash because they are asynchronously displayed and so for a short time their contents are not ready yet. Try setting
neverShowPlaceholderstoYESon the cell nodes. More information can be found here.