美文网首页IOS 菜鸟进阶
【转载】如何对UItableviewd的滚动加载进行优化,防止卡

【转载】如何对UItableviewd的滚动加载进行优化,防止卡

作者: 学呀学呀总得学会了吧 | 来源:发表于2018-11-29 21:44 被阅读22次

    UITableView

    UITableView最核心的思想就是UITableViewCell的重用机制。简单的理解就是:UITableView只会创建一屏幕(或一屏幕多一点)的UITableViewCell,其他都是从中取出来重用的。每当Cell滑出屏幕时,就会放入到一个集合(或数组)中(这里就相当于一个重用池),当要显示某一位置的Cell时,会先去集合(或数组)中取,如果有,就直接拿来显示;如果没有,才会创建。这样做的好处可想而知,极大的减少了内存的开销。

    知道UITableViewCell的重用原理后,我们来看看UITableView的回调方法。UITableView最主要的两个回调方法是tableView:cellForRowAtIndexPath:和tableView:heightForRowAtIndexPath:。理想上我们是会认为UITableView会先调用前者,再调用后者,因为这和我们创建控件的思路是一样的,先创建它,再设置它的布局。但实际上却并非如此,我们都知道,UITableView是继承自UIScrollView的,需要先确定它的contentSize及每个Cell的位置,然后才会把重用的Cell放置到对应的位置。所以事实上,UITableView的回调顺序是先多次调用tableView:heightForRowAtIndexPath:以确定contentSize及Cell的位置,然后才会调用tableView:cellForRowAtIndexPath:,从而来显示在当前屏幕的Cell。

    举个例子来说:如果现在要显示100个Cell,当前屏幕显示5个。那么刷新(reload)UITableView时,UITableView会先调用100次tableView:heightForRowAtIndexPath:方法,然后调用5次tableView:cellForRowAtIndexPath:方法;滚动屏幕时,每当Cell滚入屏幕,都会调用一次tableView:heightForRowAtIndexPath:、tableView:cellForRowAtIndexPath:方法。

    UITableView的优化主要从三个方面入手:

    1.提前计算并缓存好高度(布局),因为heightForRowAtIndexPath:是调用最频繁的方法;

    2.异步绘制,遇到复杂界面,遇到性能瓶颈时,可能就是突破口;

    3.滑动时按需加载,这个在大量图片展示,网络加载的时候很管用!(SDWebImage已经实现异步加载,配合这条性能杠杠的)。

    开发的过程中,自定义Cell的种类千奇百怪,但Cell本来就是用来显示数据的,不说100%带有图片,也差不多,这个时候就要考虑,下滑的过程中可能会有点卡顿,尤其网络不好的时候,异步加载图片是个程序员都会想到,但是如果给每个循环对象都加上异步加载,开启的线程太多,一样会卡顿,我记得好像线程条数一般3-5条,最多也就6条吧。这个时候利用UIScrollViewDelegate两个代理方法就能很好地解决这个问题。

    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate

    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

       思想就是识别UITableView禁止或者减速滑动结束的时候,进行异步加载图片,快滑动过程中,只加载目标范围内的Cell,这样按需加载,极大的提高流畅度。而SDWebImage可以实现异步加载,与这条性能配合就完美了,尤其是大量图片展示的时候。而且也不用担心图片缓存会造成内存警告的问题。

    //获取可见部分的Cell

    NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];

            for (NSIndexPath *indexPath in visiblePaths)

            {

            //获取的dataSource里面的对象,并且判断加载完成的不需要再次异步加载

                <code>

            }

       记得在记得在“tableView:cellForRowAtIndexPath:”方法中加入判断:

    // tableView 停止滑动的时候异步加载图片

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

            if (self.tableView.dragging == NO && self.tableView.decelerating == NO)

                {

                  //开始异步加载图片

                    <code>

                }

    除了上面最主要的三个方面外,还有很多几乎大伙都很熟知的优化点:

    1.正确使用reuseIdentifier来重用Cells

    2.尽量使所有的view opaque,包括Cell自身

    3.尽量少用或不用透明图层

    4.如果Cell内现实的内容来自web,使用异步加载,缓存请求结果

    5.减少subviews的数量

    6.在heightForRowAtIndexPath:中尽量不使用cellForRowAtIndexPath:,如果你需要用到它,只用一次然后缓存结果

    7.尽量少用addView给Cell动态添加View,可以初始化时就添加,然后通过hide来控制是否显示


    此文为转发用于记录总结 ,感谢大神们的总结分享。

    http://www.cocoachina.com/ios/20150602/11968.html

    相关文章

      网友评论

        本文标题:【转载】如何对UItableviewd的滚动加载进行优化,防止卡

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