关于tableView的显示优化

前言:相信大家都使用过SDWebImage这么一个三方框架吧.对,这个框架写的真心的不错.使用过这个框架,就一定要了解它内部的实现过程,否则糊里糊涂的使用,那天不更新了,怎么办.

这篇文章主要是介绍SDWebImage加载网络图片的基本原理.

tableView是我们做APP的时候,使用率最多的一个控件了,我敢说一个app没有tableView的话,它都不好意思说自己是个app,更别说上架了.

说到tableView,其实它本身就是一个比较好的控件,既继承了scrollView的滚动,又有缓存池这么一个特别的存储方式(重复利用) .但是一旦涉及到网络,它变有点捉襟见肘了,异步请求,主线程更新,cell高度 等等的问题,造成了它的显示问题.

下来我给大家说一说,初步的优化方案.
1.我一用户为出发点进行说明,用户肯定要使用比较省流量的客户端,如果进一次就下载一次,是不是很耗流量.

对应的,我们不应该直接从网络上直接请求数据, 应该先从用户手机的cache中取搜寻(哪个文件夹---->根据你从网络上请求的数据下载到哪. 为什么是cache,这个是苹果沙盒中就只有这个文件夹,我们还能存了,其他的不好意思,苹果会做特殊处理的 :document--->这里放东西,对不起,别想上架了.preference---> 偏好设置, 一般放配置相关的参数. temp--->临时数据(会自动删除的) )

  1. 网络请求的存放方式 ---->1>直接存放在cache.2>更新显示.
    这里对于网络请求我们也需要优化,保证每个下载只有一个进程,当图片下载完成后,要及时移除进程.如果当前cell下载已有进行,就不必去创建新的线程进行下载. 如果图片长时间无法被下载下来,要及时停止当前的任务(双进程,可能下载好了以后又会被新进程的下载覆盖)

3.对于用户,最快的方式读取数据,不应该是什么路径读取,而是自己的程序内直接读取最好.(所以网络上下载的数据应该在程序内也保存一份.)
不用担心,程序会变大,应为这一部分数据,只要已退出界面,就会马上被移除的

下载用一张图表进行一个详细的说明
如果没有沙盒的话:


Snip20150917_1.png

如果有沙盒的话:


Snip20150917_2.png

下面我把代码程序附带一份---->仅供参数

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"app"];
    
    AppModel *appModel = self.apps[indexPath.row];
    
    cell.textLabel.text = appModel.name;

    cell.detailTextLabel.text = appModel.download;
    
    // 占位图片
    cell.imageView.image = [UIImage imageNamed:@"kk_fruit_link_180px_1186831_easyicon.net"];
    // 从图片缓存中取, 如果取不到
    if (!self.iconCache[appModel.icon]) {  
        NSLog(@"没有缓存");
        NSString *cache = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
        NSLog(@"%@",cache);
        NSString *file = [appModel.icon lastPathComponent];
        NSString *path = [cache stringByAppendingPathComponent:file];
        
        __block NSData *data = [NSData dataWithContentsOfFile:path];
        // 从内存中取,如果取不到
        if (data == nil) {
            NSLog(@"没有数据");
            
            NSOperationQueue *queue = [[NSOperationQueue alloc]init];
            NSBlockOperation *blockOpertion = self.blockOperation[appModel.icon];
            // 判断是否被下载,若果没有下载线程
            if (blockOpertion == nil) {
                NSLog(@"没有数据,没有线程");
                blockOpertion = [NSBlockOperation blockOperationWithBlock:^{
                    
                    NSURL *url = [NSURL URLWithString:appModel.icon];
                    
                    data = [NSData dataWithContentsOfURL:url];
               // 有线程,但没有下载下来的话,删除线程,重新下载 (保证一个图片,只有一个线程来控制)
                    
                if (data == nil) {
                    NSLog(@"下载不下来,需要重新下载");
                    [self.blockOperation removeObjectForKey:appModel.icon];
                    return ;
                }
                // 下载下来的数据,返回图片
                UIImage *image = [UIImage imageWithData:data];
                // 图片放入缓存
                self.iconCache[appModel.icon] = image;
                // 数据进行储存
                [data writeToFile:path atomically:YES];
                
                // 将图片返回主线程,并赋值UI
                [[NSOperationQueue mainQueue]addOperationWithBlock:^{
                    //                    cell.imageView.image = self.iconCache[appModel.icon];
                    
                    // 刷新数据  ,不让数据复用
                    [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
                    // 下载成功移除操作
                    [self.blockOperation removeObjectForKey:appModel.icon];
                    }];
                }];
                
                // 添加操作到队列中
                [queue addOperation:blockOpertion];
            }   
        }else{
            // 如果内存中有数据
            NSLog(@"没有缓存,但有数据");
            // 取出数据,返回图片
        UIImage *image = [UIImage imageWithData:data];
            // 图片放入缓存
            self.iconCache[appModel.icon] = image;
            // UI赋值
            cell.imageView.image = self.iconCache[appModel.icon];
        }
    }
    else{
        // 如果有缓存。直接赋值
        NSLog(@"有缓存");
        cell.imageView.image = self.iconCache[appModel.icon];   
    }
  return cell;
   }

这里我要说明的是,我是以模型为基本跨度,用模型属性参数,作为键, 用来保存任务,以及程序的缓存. 并且也组成文件存储的全路径. 这样的话,比较方便存取数据. 因为本来就是要取出模型数据,因为模型数据的不同,而赋了不同的值. 又方便,又具有区分性.

这里建立了两个字典 : 1.iconCache:保存缓存的图片
2.blockOperation 用来保存 下载任务 (程序里面有一个没有定义好 ,结果有个很像的名字NSBlockOperation *blockOpertion 这个是定义任务的. 对不起各位了).

说到这里,总算将网络处理这方面讲的差不多了, 现在就来说说SDWebImage的强大.

SDWebImage的操作

对于以上的程序在SDWebImage中只需要一句代码就已经处理完全了.
在它的"UIImageView+WebCache.h"中已经将这部分代码已经封装完全了.

[cell.imageView sd_setImageWithURL:[NSURL URLWithString:appModel.icon] placeholderImage:image];
tableView的二次优化

这里就需要用到绘图的知识了.什么是imageView,其实它根本就是在一个view的上面图层上进行绘画,将图片画上去,然后将用户的交互给取了而已. 那我们是不是可以将cell 的imageView也给取了,然后只建立一个空白的view,在上面绘画就行了. 这样就会相比与以前少了一些imageview. 相当于 节省了很多控件吧. (性能相对也会减少不少).

我曾经想过一个问题, 比如绘画 (会不会很耗时), 其实imageView何尝不是一个耗时的操作(它又要创建,又要画), 从这里就可以看出,绘画是一个不错的选择.

可能大家觉得绘画,多么麻烦呀. 不错确实很麻烦,特别是cell的高度不确定得时候,会显得额外麻烦.但是我想你的服务器也不会傻到不给你传想过图片的宽高吧, 对于多组图片你利用9宫格思想将其缩小绘画(又美观又节省控件和空间).

如果imageview真的很多的时候,绘画的优势就体现出来了,因为控件加载的少了,相当于系统的消耗就会变得很少,系统就会流畅了很多.

这段代码我就不着急写了. 谢谢了. (我想说程序是有感情的,有思想的, 他们的这些,其实都是我们程序员所赋予的, 所以少年不断的学习吧, 让自己喜欢上思考,喜欢上编程吧, 让自己的程序有感情吧).

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62
  • 归纳查经法: 观察(Who/When/What/Why/Where/How)解释应用 一,经文 1.耶和华是我的亮...
    guxi_754c阅读 9,233评论 0 0
  • 分享一个我自己改变前的故事,每个女人都喜欢能够在家里有一个自己的地位,有一个爱自己的老公,能和婆婆处的来,但是往往...
    元小英阅读 184评论 17 0
  • 图片随意插入的,与具体情境不符! 心泉会所离自己也就20分钟的车程,一直想去看看,一直没有时间。这次是逃课,也没有...
    艳敏姐阅读 429评论 10 6
  • 各位朋友们早上好,已经进入五月份了,空气中到处弥漫着香樟树换新叶后的甜香,今天在下雨,我颇不喜下雨的日子,...
    朵朵DD阅读 417评论 0 0