UICollectionView滑动流畅性优化
UICollectionView滑动流畅性优化
前言
初始的collection view在滑动时都是十分流畅的,然而因为collection view cell 加载更多的内容时因为主线程耗用太多性能而导致主线程出现堵塞,导致原本流畅的滑动出现卡顿的情况。
collection view加载cell时一般会常用复用池,所以滑动时每要显示一个cell都会调用协议中- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
的方法,而在这方法中除了返回复用池中的cell,程序猿还可以趁机在其中调用cell自定义的读取数据的方法(姑且称之为-(void)loadData:
),在本文中即将展示如何将- (void)loadData:
中的耗时操作放入NSOperationQueue中并发进行从而不影响collection view的滑动,同时在用户快速滑动中,单个cell的NSOperationQueue
中会堆积大量operation
的情况,也将在本文中提出应对方法。
NSOperationQueue和NSInvocationOperation
NSOperationQueue将线程操作以队列的形式展现,初始化代码如下:
_queue = ({
NSOperationQueue *q = [[NSOperationQueue alloc]init];
//设置最大并行操作数为1相当于将queue设置为串行线程
q.maxConcurrentOperationCount = 1;
q;
});
每一个operation都是这个队列中的一个元素,而这个元素在满足条件的情况下可以在不用执行就从队列中移除,我们可以利用这种特性来取消其中一些未执行但是不必执行的operation ,关键代码如下:
if (self.operationQueue.operationCount >= 2) {
[self.operationQueue cancelAllOperations];
}
NSInvocationOperation *op = [[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(operationSelector:)
object:dic];
[self.operationQueue addOperation:op];
其中-(void)cancelAllOperations
可以让队列里的所有待执行的operation移除出队列(详情看官方文档),要注意,如果执行此方法时有operation正在执行,那么那些正在执行的operation不会被强行中止并取消。
Canceling the operations does not automatically remove them from the queue or stop those that are currently executing. For operations that are queued and waiting execution, the queue must still attempt to execute the operation before recognizing that it is canceled and moving it to the finished state.——苹果官方开发文档
NSInvocationOperation是NSOperation的子类,它和NSBlockOperation一样都可以作为元素添加到NSOperationQueue
中等待执行,最主要的区别在于前者带的是@selector
后者带的是block
。
异步操作中因视图原因导致程序崩溃时的应对方法
原本高高兴兴把耗时的代码都放到队列中运行时却发现在涉及到视图操作的地方容易出现错乱,甚至是BAD_XXXX之类的崩溃时,就需要检查@selector
中是否包含类似addSubview
,removeFromSubview
之类的傻X操作(每读取一次数据就把view
移出来/放进去是什么鬼操作?!View:我来了,我又走了,我来了,我又走了,你打我呀……),遇到这种代码第一想到的是尽量将其移出Operation
,最好是将其放到初始化的方法,但是还有些情况是有些视图的属性受到数据的影响,需要等耗时操作结束之后才能确定视图的属性,这个时候就要用到GCD的方法了,如下:
- (void)optimizeOperation:(NSString *)dataStr {
//模拟十分耗时间的操作,注意,这里不能放在main_queue里面执行,否则时间还是消耗在了主线程里面
[NSThread sleepForTimeInterval:0.05];
if ([dataStr isEqualToString:self.dataStr]) {
dispatch_async(dispatch_get_main_queue(), ^{
self.titleLb.text = dataStr;
});
}
}
要注意dispatch_async(dispatch_get_main_queue(), ^{})
中不要有耗时的方法,我们到目前为止的铺垫都是为了让占用主线程的滑动操作不要被其他操作堵塞,如果把耗时操作放进去的话就前功尽弃了。
附带demo地址,本文所涉及的思路体现在TextCell.m中:https://github.com/MrYu4/OptimizeCollectionView
可能存在的疑问
- 可是我就是不想用NSInvocationOperation啊,我用NSBlockOperation不行吗?
行
if (self.operationQueue.operationCount >= 2)
这个判断语句怎么理解?
队列中如果有两个或两个以上个待出队列的
operation
,那么第一个可能是正在执行中的,第二个或者之后都是未执行的(忘了说了,queue设置了最多可并发运行一个operation
),这个时候正好是有新的operation
等待加入,就说明以往的operation
没什么用了,这个时候就可以进行剪枝操作,把operation
除去节省性能。
- 接着上个问题,为什么不是>=1呢
[self.operationQueue cancelAllOperations];
能立刻去除的是未执行的operation
,但正在执行的不会除掉,也就是在cancelAllOperations
之前队列内元素个数=1时,就基本上可以确定队列中没有可以除掉的operation
了。
求打赏
UICollectionView滑动流畅性优化的更多相关文章
- UITableVIew 滚动流畅性优化
影响UITableViewUITableView滚动的流畅性原因: 1. 在代理方法中做了过多的计算占用了 UI 线程的时间 2.同上 3.Cell 中 view 的组织复杂,比如使用layer并不会 ...
- UITableView 滚动流程性优化
影响 UITableView 滚动的流畅性的原因 1. 在代理方法中做了过多的计算占用了 UI 线程的时间 2.同上 3.Cell 中 view 的组织复杂 关于第一点,首先要明白 tablevi ...
- iOS的流畅性
1优先级别不同:iOS最先响应屏幕 优先级别不同:iOS最先响应屏幕 当我们使用iOS或者是Android手机时,第一步就是滑屏解锁找到相应程序点击进入.而这个时候往往是所有操控开始的第一步骤,iOS ...
- 让页面滑动流畅得飞起的新特性:Passive Event Listeners
版权声明:本文由陈志兴原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/153 来源:腾云阁 https://www.qclo ...
- ios UICollectionView滑动时操作
点开UICollectionViewDelegate,发现有@protocol UICollectionViewDelegate <UIScrollViewDelegate>. 所以只要实 ...
- UIScrollView的delegate方法妙用之让UICollectionView滑动到某个你想要的位置
一个UICollectionView有好多个cell,滑动一下,谁也不知道会停留在哪个cell,滑的快一点,就会多滑一段距离,反之则会滑的比较近,这正是UIScrollview用户体验好的地方. 如果 ...
- Spring配置表友好性优化思路
Spring配置表需要尽量保证对程序员的友好性,一下提供一种优化思路. 中途未保存,心态炸了,只贴图了,fuuuuuuuuuuuuuck 第一种(最烂,最不友好):以Json的格式保存在配置表中,程序 ...
- Android Developers:使ListView滑动流畅
流畅滑动ListView的关键是保持应用程序的主线程(UI线程)从免于繁重处理.确保你的任何硬盘访问,网络访问或者SQL访问在一个单独的线程中.为了测试你的应用个程序的状态,你能启动StrictMod ...
- iOS开发之加载、滑动翻阅大量图片优化解决方案
本文转载至 http://mobile.51cto.com/iphone-413267.htm 今天分享一下私人相册中,读取加载.滑动翻阅大量图片解决方案,我想强调的是,编程思想无关乎平台限制.我要详 ...
- UI的流畅度优化
Android中所有的界面绘制工作都是在UI线程中进行的,提高UI流畅度的最核心根本在于释放UI线程.即:不在主线程中做耗时的操作. 很多人都知道,耗时的操作要放到子线程中去做,比如访问网络,比如读写 ...
随机推荐
- VisualStudio 使用 FastTunnel 辅助搭建远程调试环境
有时候需要远程调试一些用户问题,期望能使用本机的 Visual Studio 开发环境,调试远程的用户的设备上的应用.这时会遇到的一个问题是如何让本机的 Visual Studio 可以连接上远程的用 ...
- 【内存优化】Oracle 的SGA与Linux的shmall和shmmax的关联
查看linux下的Oracle共享内存段 [oracle@oradb ~]$ ipcs -m ------ Shared Memory Segments -------- key shmid owne ...
- Android 开发中脚本 提高效率工具
在安卓开发中我们常常需要获取日志,通常我们可以通过adb logcat 命令获取日志.同样,我没有可以通过脚本获取.其实质也是通过adb命令实现,只是把命名写入bat文件中,在win系统中直接双击就可 ...
- Splashtop和 TiFlux 宣布建立合作伙伴关系
2020年9月21日,远程访问解决方案的全球领导者 Splashtop Inc. 和面向 IT 服务提供商的 IT 解决方案公司 TiFlux 宣布建立合作伙伴关系,以整合 Splashtop 远程访 ...
- mysql命令最新
查看授权 mysql> select user,host from mysql.user; +--------+------------+ | user | host | +--------+- ...
- layui 新增行
layui表格新增行目前只在从内存加载数据的情况下可行! 在多方查找数据与实验后,我发现layui确实只能在直接赋值数据(从内存加载数据)的情况下新增行,即首次渲染表格时使用内存数据给表格的data参 ...
- kubernets之pod的生命周期容器启动后钩子以及容器结束前钩子
一 先来介绍容器启动后钩子 1.1 容器启动后钩子,并不是容器启动之后才会执行的操作,而是在容器启动过程中,异步的和容器进行启动的一种钩子它有2种表现形式,包括我们后面提到的容器结束前钩子一样 在一 ...
- 腾讯云服务器Ubuntu-配置mysql,nginx,nodejs
趁着618腾讯云服务器的促销活动,笔者买了最低配置的云服务器,用作学习. 接上一篇文章的内容,系统方面选择了Ubuntu,版本是20.04 LTS. 选择Ubuntu的原因,主要是因为Ubuntu一 ...
- Python作图三维等高面
技术背景 对于等高线,大家都是比较熟悉的,因为日常生活中遇到的山体和水面,都可以用一系列的等高线描绘出来.而等高面,顾名思义,就是在三维空间"高度一致"的曲面.当然了,在二维平面上 ...
- etcd MVCC 存储结构及流程
什么是 MVCC MVCC 是 Multi-Version Concurrency Control 的缩写,即多版本并发控制.它是一种并发控制的方法,用于在数据库系统中实现事务的隔离性.MVCC 是一 ...