前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CFRunloop 优化TableView加载高清大图UI卡顿问题。单独分批加载

CFRunloop 优化TableView加载高清大图UI卡顿问题。单独分批加载

作者头像
星宇大前端
发布2019-01-15 15:25:44
1.9K0
发布2019-01-15 15:25:44
举报
文章被收录于专栏:大宇笔记

TableView卡顿环境分析:

tableView加载过多的高清大图,Runloop不只处理iOS事件,渲染图形也是runloop处理的。

      而渲染图形的UI操作必须在主线程中,不能开辟线程进行图形处理。

      在拖动tableView的时候,Runloop要处理拖动事件,还要处理过多图片渲染,而造成卡顿。

解决卡顿分析:

      1、Runloop在一次循环渲染图片过多,那就让Runloop一次处理一张图片

      2、将处理图片的代码放在block中,然后加入数组中,处理几次加入几次。

      3、我们只需要渲染,tableView显示的图片,显示图片有最大个数。移开屏幕或者不处理的从队列数组里删去。

2和3其实就是逻辑的问题,不赘述了,下面会给出demo源码。主要讲讲第一个问题,是处理卡顿的重点。

第一个问题实现代码如下:

#pragma mark  设置runloop监听

//这里面都是C语言 -- 添加一个监听者

-(void)addRunloopObserver{

//获取当前runloop

CFRunLoopRef  currentRunloop =  CFRunLoopGetCurrent();

//runloop观察者上下文, 为下面创建观察者准备,只有创建上下文才能在回调了拿到self对象,才能进行我们的逻辑操作. 这是一个结构体。

/**

     typedef struct {

     CFIndex version;

     void * info;

     const void *(*retain)(const void *info);

     void (*release)(const void *info);

     CFStringRef (*copyDescription)(const void *info);

     } CFRunLoopObserverContext;

     **/

CFRunLoopObserverContext  context = {

0,

        (__bridge void *)(self),

        &CFRetain,

        &CFRelease,

NULL

    };

//创建Runloop观察者  kCFRunLoopBeforeWaiting  观察在等待状态之前  runloop有下面几种状态 看英文应该知道了。

/*

     kCFRunLoopEntry = (1UL << 0),

     kCFRunLoopBeforeTimers = (1UL << 1),

     kCFRunLoopBeforeSources = (1UL << 2),

     kCFRunLoopBeforeWaiting = (1UL << 5),

     kCFRunLoopAfterWaiting = (1UL << 6),

     kCFRunLoopExit = (1UL << 7),

     kCFRunLoopAllActivities = 0x0FFFFFFFU

     */

static CFRunLoopObserverRef  obserberRef;

    obserberRef =CFRunLoopObserverCreate(NULL, kCFRunLoopBeforeWaiting, YES, 0,&callback, &context);

//给当前runloop添加观察者

CFRunLoopAddObserver(currentRunloop, obserberRef, kCFRunLoopDefaultMode);

//释放观察者

CFRelease(obserberRef);

}

//观察回调

static void callback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info){

ViewController * vcSelf = (__bridge ViewController *)(info);

if (vcSelf.TaskMarr.count > 0) {

//获取一次数组里面的任务并执行

runloopTask  task  =  vcSelf.TaskMarr.firstObject;

        task();

        [vcSelf.TaskMarr removeObjectAtIndex:0];

    }else{

return;

    }

}

代码分析:

  • 先推理下,如果我要把任务放到Runloop里操作,首先我要获取Runloop。
  • 然后我们需要一个观察者,找一个时机把任务放进去。如果对runloop了解的话,会想到CFRunLoopObserver.然后我们创建一下这个观察者对象。
  • 然后把观察者扔进runloop,这样我们就能拿到,Runloop等待之前的回调。
  • 然后把任务扔到回调中。

注意:这样还没有结束,还有一个问题待解决。那就是runloop运行一次任务就会休眠了。不会把你数组队列的任务进行处理。所以你要让Runloop不断的运行,直到你的任务结束。

方案如下:

//给runloop一个事件源,让Runloop不断的运行执行代码块任务。

    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(runloopalive) userInfo:nil repeats:YES];

//如果方法里什么都不干,APP性能影响并不大。但cpu增加负担,

-(void)runloopalive{

//什么都不干

}

效果如下:

demo地址:https://github.com/RainManGO/tableView-Caton-optimization

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017年06月08日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云代码分析
腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档