美文网首页
UIColletionView性能调研结果

UIColletionView性能调研结果

作者: 宋奕Ekis | 来源:发表于2019-03-16 22:38 被阅读0次

    UIColletionView性能调研结果

    在之前的code review会议中,遗留了两个问题:

    一、

    1. 复用cell,cell中嵌套子view

    2. 全部使用复用cell

      哪种性能更好?

    1. cell中的子View,使用addSubView和removeFormSuperView来控制子View显示与隐藏

    2. cell中的子View,一次性addSubView,然后使用hidden属性,来控制子view显示与隐藏

      哪种性能更好?

    上述是使用文字表述可能理解起来略加困难,我们具体可以参考以下代码。并附上相应代码的视频,可以直观的看出性能的变化情况

    一、

    1. 复用cell,cell中嵌套子view

      每个UICollectoinViewCell中包含10个子view。

      UICollectoinView 总共返回5000个cell。每个cell的长宽为屏幕的1/3。总共15000个view

      代码表述如下:

    ​
    @implementation ReuseAllView
    - (instancetype)initWithFrame:(CGRect)frame {
     if (self = [super initWithFrame:frame]) {
     [self setUpView];
     }
     return self;
    }
    ​
    - (void)setUpView {
     NSInteger i = 0;
     CGFloat margin = 10;
     NSInteger count_row = 10;
     CGFloat v_w = (CGRectGetWidth(self.frame) - (count_row - 1)*margin)/count_row;
     for (; i<count_row; i++) {
     UIView *view = [[UIView alloc]initWithFrame:CGRectMake(i*(margin+v_w), 0, v_w, CGRectGetHeight(self.frame))];
     view.backgroundColor = [UIColor blueColor];
     [self.contentView addSubview:view];
     }
    }
    @end
    
    #import "ViewController.h"
    #import "reuseview/ReuseViewCell.h"
    #import "reuseview/ReuserCellCell.h"
    #import "reuseview/ReuseAllCell.h"
    #import "reuseview/ReuseAllView.h"
    ​
    #define UseCell ReuseAllCell
    ​
    @interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>
    @property (nonatomic, strong)UICollectionView *colletionView;
    @end
    ​
    @implementation ViewController
    ​
    - (void)viewDidLoad {
     [super viewDidLoad];
     [self.view addSubview:self.colletionView];
    }
    ​
    - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
     return 1;
    }
    ​
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
     return 5000;
    }
    ​
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
     UseCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([UseCell class]) forIndexPath:indexPath];
     if ([cell respondsToSelector:@selector(updateView)]) {
     [cell performSelector:@selector(updateView)];
     }
     return cell;
    }
    ​
    - (UICollectionView *)colletionView {
     if (!_colletionView) {
     UICollectionViewFlowLayout *flowlayout = [[UICollectionViewFlowLayout alloc]init];
     flowlayout.scrollDirection = UICollectionViewScrollDirectionVertical;
     flowlayout.minimumLineSpacing = 0.;
     flowlayout.minimumInteritemSpacing = 0.;
     flowlayout.estimatedItemSize = CGSizeZero;
     flowlayout.itemSize = CGSizeMake(self.view.frame.size.width/3, self.view.frame.size.width/3);
     _colletionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) collectionViewLayout:flowlayout];
     _colletionView.backgroundColor = [UIColor whiteColor];
     [_colletionView registerClass:[UseCell class] forCellWithReuseIdentifier:NSStringFromClass([UseCell class])];
     _colletionView.delegate = self;
     _colletionView.dataSource = self;
     }
     return _colletionView;
    }
    ​
    @end
    

    滑动到最底部,再滑动到最顶部,性能反馈如下:

    image
    1. 全部使用复用cell。

      UIColloctionView返回总共15000个cell。每个cell宽屏幕的1/30。长屏幕的1/3。

      代码表述如下:

        #import "ReuseAllCell.h"
        ​
        @implementation ReuseAllCell
        - (instancetype)initWithFrame:(CGRect)frame {
         if (self = [super initWithFrame:frame]) {
         self.backgroundColor = [UIColor orangeColor];
         }
         return self;
        }
        @end
    
        #import "ViewController.h"
        #import "reuseview/ReuseViewCell.h"
        #import "reuseview/ReuserCellCell.h"
        #import "reuseview/ReuseAllCell.h"
        #import "reuseview/ReuseAllView.h"
        ​
        #define UseCell ReuseAllCell
        ​
        @interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>
        @property (nonatomic, strong)UICollectionView *colletionView;
        @end
        ​
        @implementation ViewController
        ​
        - (void)viewDidLoad {
         [super viewDidLoad];
         [self.view addSubview:self.colletionView];
        }
        ​
        - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
         return 1;
        }
        ​
        - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
         return 5000*3;
        }
        ​
        - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
         UseCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([UseCell class]) forIndexPath:indexPath];
         if ([cell respondsToSelector:@selector(updateView)]) {
         [cell performSelector:@selector(updateView)];
         }
         return cell;
        }
        ​
        - (UICollectionView *)colletionView {
         if (!_colletionView) {
         UICollectionViewFlowLayout *flowlayout = [[UICollectionViewFlowLayout alloc]init];
         flowlayout.scrollDirection = UICollectionViewScrollDirectionVertical;
         flowlayout.minimumLineSpacing = 0.;
         flowlayout.minimumInteritemSpacing = 0.;
         flowlayout.estimatedItemSize = CGSizeZero;
         flowlayout.itemSize = CGSizeMake(self.view.frame.size.width/30, self.view.frame.size.width/3);
         _colletionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) collectionViewLayout:flowlayout];
         _colletionView.backgroundColor = [UIColor whiteColor];
         [_colletionView registerClass:[UseCell class] forCellWithReuseIdentifier:NSStringFromClass([UseCell class])];
         _colletionView.delegate = self;
         _colletionView.dataSource = self;
         }
         return _colletionView;
        }
        ​
        @end
    

    滑动到最底部,再滑动到最顶部,性能反馈如下:

    image

    可以从视频上看出:无论从CPU峰值还是,RAM的占用情况,全部复用cell的性能都比复用cell再嵌套view的性能要差一些。

    1. cell中的子View,使用addSubView和removeFormSuperView来控制子View显示与隐藏

      UICollectionView总共返回5000个cell。

      其中每个cell中嵌套500个view。

      代码表述如下:

        #import "ReuseViewCell.h"
        @interface ReuseViewCell ()
        @property (nonatomic, strong)NSMutableArray *views;
        @end
        @implementation ReuseViewCell
        - (instancetype)initWithFrame:(CGRect)frame {
         if (self = [super initWithFrame:frame]) {
         self.views = [NSMutableArray array];
         [self setUpView];
         }
         return self;
        }
        ​
        - (void)setUpView {
         if (self.views.count) {
         [self updateView];
         } else {
         for (NSInteger i = 0; i<500; i++) {
         UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame))];
         view.backgroundColor = [UIColor redColor];
         [self.contentView addSubview:view];
         [self.views addObject:view];
         }
         }
    
        }
        ​
        - (void)updateView {
         [self.views makeObjectsPerformSelector:@selector(removeFromSuperview)];
         for (UIView *view in self.views) {
         [self.contentView addSubview:view];
         }
        }
        @end
    

    滑动到最底部,再滑动到最顶部,性能反馈如下:

    image
    1. cell中的子View,一次性addSubView,然后使用hidden属性,来控制子view显示与隐藏。

    UICollectionView返回5000个cell,每个cell中嵌套500个view。

    代码表述如下:

            #import "ReuserCellCell.h"
            @interface ReuserCellCell ()
            ​
            @end
            @implementation ReuserCellCell
            - (instancetype)initWithFrame:(CGRect)frame {
             if (self = [super initWithFrame:frame]) {
             [self setUpView];
             }
             return self;
            }
            ​
            - (void)setUpView {
             if (self.contentView.subviews.count) {
             [self updateView];
             } else {
             for (NSInteger i = 0; i<500; i++) {
             UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame))];
             view.backgroundColor = [UIColor greenColor];
             [self.contentView addSubview:view];
             }
             }
            }
            ​
            - (void)updateView {
             [self.contentView.subviews makeObjectsPerformSelector:@selector(setHidden:) withObject:@(YES)];
             [self.contentView.subviews makeObjectsPerformSelector:@selector(setHidden:) withObject:@(NO)];
            }
            @end
    

    滑动到最底部,再滑动到最顶部,性能反馈如下:

    image

    从上述结果,可以很明显的看出,第一种方式比第二种方式,无论从cup使用率还是RAM的占用情况,都差了很多,并且,第一种方式,明显造成了页面卡顿。

    于此同时,在代码中,第一种方式的写法也会造成不必要的内存占用

    综上所述,后续我们在使用复用机制的时候,例如日历,可以复用大cell然后嵌套子View去实现,并且,一定要一次性addSubView后再单独控制子view的显示。此种做法,对于性能的要求最小

    相关文章

      网友评论

          本文标题:UIColletionView性能调研结果

          本文链接:https://www.haomeiwen.com/subject/jsbemqtx.html