美文网首页
Table View 中图片加载逻辑的优化

Table View 中图片加载逻辑的优化

作者: Crazy2015 | 来源:发表于2017-05-03 18:59 被阅读168次

    当 scroll view 开始滚动时,scroll view 的 delegate 会不断的收到很多回调消息,这些消息告诉我们 scroll view 处于什么状态。通过官方的文档,我们知道用户在和 scroll view 交互时有两种手势,一种是 flick(轻扫),一种是 drag(拖动)。
    但是在实际的操作过程中,用户很可能会带来更复杂的交互,经过实践归纳总结,我将它们大概分成四种情况,如下图:

    131122-45c05f3fa99c875c.png
    1. 橙色线,用户用手指轻扫一下屏幕,然后释放手指。
    2. 橙色线->绿色线->蓝色线,用户拖动 scroll view,并在 scroll view 处于静止时释放手指。
    3. 橙色线->红色线->…->橙色线,用户在 scroll view 停止滚动前,不断的轻扫屏幕,最后释放手指。
    4. 橙色线->红色线->…->橙色线->绿色线->紫色线,用户在轻扫屏幕后,手指突然定住 scroll view,最后释放手指。

    Glow 的这篇博文中提到了当年 Tweetie 的方案以及自己的优化方案,大概的思路就是,当用户在快速滑动 table view 时,cell 不加载图片,对应上面的情况三。那么如何定义这个快速滑动的情况呢?

    快速滑动就是用户不断的 flick 屏幕,也就是在上一次 scroll view 还未停止的时候开始下一次短暂拖动,这就导致 scroll view 一直处于滚动状态。

    如果我们想单纯的让 table view 在快速滚动的过程中不加载图片的话,
    分析如下:

    1. 当用户手动 drag table view 的时候,会加载 cell 中的图片;
    2. 在用户快速滑动的减速过程中,不加载过程中 cell 中的图片(但文字信息还是会被加载,只是减少减速过程中的网络开销和图片加载的开销);
    3. 在减速结束后,加载所有可见 cell 的图片(如果需要的话);
    现在的问题就在于怎么区分判断用户是在拖动还是减速过程

    因为:
    前面提到,刚开始拖动的时候,dragging 为 YES,decelerating 为 NO;decelerate 过程中,dragging 和 decelerating 都为 YES;decelerate 未结束时开始下一次拖动,dragging 和 decelerating 依然都为 YES。所以无法简单通过 table view 的 dragging 和 decelerating 判断是在用户拖动还是减速过程。

    解决这个问题很简单,添加一个变量如 userDragging,在 willBeginDragging 中设为 YES,didEndDragging 中设为 NO。

    那么 tableView: cellForRowAtIndexPath: 方法中,是否 load 图片的逻辑就是:

    if (!self.userDragging && tableView.decelerating) {  
    //这个条件就是说明是在快速滑动过程中,并且没有拖动的情况下
        cell.imageView.image = nil;
    } else {
        // code for loading image from network or disk
    }
    
    问题2: 只做 decelerating 的判断可以让 table view 在快速滚动的过程中做到完全不加载图片。但是这样做还是会产生两个问题,

    1,当 table view 在停止快速滑动正常减速结束后,屏幕上的 cell 都是不带图片的。

    这个问题比较好解决,Glow 提到的解决方法是在 scrollViewDidEndDecelerating 里面加载当前可见 cell 的图片,你需要一个形如 loadImageForVisibleCells 的方法,加载可见 cell 的图片:

    - (void)loadImageForVisibleCells
    {
        NSArray *cells = [self.tableView visibleCells];
        for (GLImageCell *cell in cells) {
            NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
            [self setupCell:cell withIndexPath:indexPath];
        }
    }
    

    这样确实解决了问题,但是却带来了新的问题,必须要等到 scroll view 完全减速完成后才会加载图片,但是 scroll view 减速的那最后一段距离实在让人难等。Glow 通过 scrollViewWillEndDragging: withVelocity: targetContentOffset: 方法的 targetContentOffset 计算出 targetRect 来加载最后可见的那些 cell。

    - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
    {
        CGRect targetRect = CGRectMake(targetContentOffset->x, targetContentOffset->y, scrollView.frame.size.width, scrollView.frame.size.height);
        self.targetRect = [NSValue valueWithCGRect:targetRect];
    }
    

    具体来说,就是用一个变量 targetRect 在 scrollViewWillEndDragging: withVelocity: targetContentOffset: 方法里面计算出值,在 scrollViewWillBeginDragging 和 scrollViewDidEndDecelerating 重置为 nil。这样一来,targetRect 还起到了之前 userDragging 的作用,可谓一举两得。

    参考地址:
    http://tech.glowing.com/cn/practice-in-uiscrollview/
    http://www.jianshu.com/p/cd12c7e57996

    相关文章

      网友评论

          本文标题: Table View 中图片加载逻辑的优化

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