QMUI_iOS
QMUI_iOS copied to clipboard
使用qmuidemo的ImagePicker的时候,在预览界面左右滑动的时候会出现跳动
请填写运行环境
- [x] 设备:
iPhone
- [x] 系统:
iOS 11.3.1
- [x] Xcode 版本:
10.1
- [x] QMUI iOS 版本:
3.1.2
请描述具体问题
使用qmuidemo的ImagePicker的时候,在预览界面左右滑动的时候会出现跳动
相关截图(断点的堆栈、控制台的 log)
这个实际刚好是要渲染后面一张图片,所以可能有点卡顿
卡顿不止是在渲染图片上,是有其他地方导致的。目前我已经优化了一波,纯图片的时候能做到没那么明显,但是相隔都是视频的时候,第一次还是有轻微的卡顿,这个需要再优化一波,思路是把设置item的操作去重。
下面是我用time profile跑出来的一些结果:
第一个是QMUIZoomImageView里面的创建和销毁video相关的控件(包括注册监听方法)。但这个部分比较奇怪。我用profile去跑QMUI的demo,并没有发现这部分耗时严重,但是我工程确出现了。然后我创了个线程去负责这块的处理。续:这部分现在发现可能是我的model层的代码有问题,取playitem的时候deliveryMode传入了image的枚举变量,然后在获取track的时候有几率会出现特别慢的情况。
第二个是如下图所示,这里置空这些东西产生的消耗也太大了,完全可以只重置上一次设置的内容就行了,不必每次都全部设置为nil。QMUI的demo有出现。简单测试时注释掉之后,明显可以减轻卡顿。
第三个地方,图中这里其实使用的是contentView的frame,那么其实用[contentView sizeTofit]就行了。但出现的原因可能是我使用了autolayout布局,QMUI中没测出来这里耗时。
=====================分割线========================= 再次补充一波优化: 因为collection的cell预加载机制,在手缓慢滑动到约1/3的时候,如果滑动稍微返回一下会加载显示占大部分的那个cell的返回滑动方向上一个cell。如果再回到最初的滑动方向,又会去加载最初滑动方向的下下个cell。 比如当前我在index为26的cell里面(先假设25和27的cell都已经加载了),往左滑到1/3时候,会去加载28的cell,然后反方向滑动,会去加载25的cell。所以在1/3的位置来回滑动的时候,会拼命地去加载28和25的cell。然后这些都会触发QMUIZoomImageView设置内容的逻辑。里面的[QMUIZoomImageView revertZooming]这个十分地消耗性能,里面有创建消耗逻辑,还有UI的needlayout。 第1点优化:QMUIImagePreviewView给cell增加一个isShowing属性,在willDisplayCell的设置为YES, didEndDisplayingCell设置为NO, 另外在cellForItemAtIndexPath里面,如果走到了[self.delegate imagePreviewView:self renderZoomImageView:zoomView atIndex:indexPath.item]; 那么给zoomview里面的reusedIdentifier赋值上Asset。 然后在前面加上判断。代码如下。这样就可以防止那些没有显示过的cell,多次进行内容设置。
......
if (!cell.isShowing) { //如果这个cell当前没有显示,且之前设置的内容都是一样的,那么不需要重新设置内容。collectionView的调用顺序是先cellforIndex然后才cellWillDisplay。所以showing大部分都是NO的。但有种情况就是在1/3处划来划去的。这种就会去预渲染没有显示的cell的图片内容。而且经常同一个cell加载同一个内容,但都不显示
QMUIZoomImageView *imageView = zoomImageView ? : [self.imagePreviewView zoomImageViewAtIndex:index];
if (imageView.reusedIdentifier && imageView.reusedIdentifier == [self.imagesAssetArray objectAtIndex:index]) {
return cell; //不需要再渲染
}
}
// 因为 cell 复用的问题,很可能此时会显示一张错误的图片,因此这里要清空所有图片的显示
[zoomView cleanContent];
if ([self.delegate respondsToSelector:@selector(imagePreviewView:renderZoomImageView:atIndex:)]) {
zoomView.reusedIdentifier = [self.imagesAssetArray objectAtIndex:index];
[self.delegate imagePreviewView:self renderZoomImageView:zoomView atIndex:indexPath.item];
}
return cell;
第2点优化:[QMUIZoomImageView revertZooming]调用次数。虽然之前已经优化了一次(在设置内容为nil的时候),但是发现还是有很多的无用调用。留意到代码里面已经在QMUIImagePreviewView 的cellWillDisplay的时候调用了这个方法,但是设置的时候又调用?是不是多余了?我的解决方法:在QMUIZoomImageView也加上isShowing的属性,这个属性的赋值跟随QMUIImagePreviewView的cell的isShowing属性。再加上一个shouldZoom的标记属性。然后把设置内容(setImage,setLivePhoto,setVideoItem)里面的
[self revertZooming];
都替换为
if (self.isShowing) {
[self revertZooming];
} else {
self.shouldZoom = YES;
}
然后把QMUIImagePreviewView 的cellWillDisplay的revertZooming改为下面的
- (void)revertZoomingIfNeed {
if (self.shouldZoom) {
[self revertZooming]; //记得在revertZooming方法里面添加上self.shouldZoom = NO;
}
}
这样处理之后,再也不会再1/3处划来划去的时候,多次调用revertZooming了
嗯嗯,总算比较顺滑了。。。
=====================分割线========================= 我居然忽略了一个最重要的优化点!预览图有必要拿原图吗?仅改为屏幕大小的图片之后,QMUI代码明显如丝般顺滑