界面卡顿优化

作者: tzhtodd | 来源:发表于2017-03-02 12:00 被阅读30次

1.除了UI部分,所有的加载操作都在后台完成。

1.1  文本计算

如果一个界面中包含大量文本,文本的宽高计算会占用很大一部分资源,并且不可避免。如果你对文本显示没有特殊要求,可以参考下 UILabel 内部的实现方式:用 [NSAttributedStringboundingRectWithSize:options:context:] 来计算文本宽高,

用 -[NSAttributedStringdrawWithRect:options:context:] 来绘制文本。尽管这两个方法性能不错,但仍旧需要放到后台线程进行以避免阻塞主线程。

如果你用 CoreText 绘制文本,那就可以先生成 CoreText 排版对象,然后自己计算了,并且 CoreText 对象还能保留以供稍后绘制使用。

1.2文本渲染

屏幕上能看到的所有文本内容控件,包括 UIWebView,在底层都是通过 CoreText 排版、绘制为 Bitmap 显示的。常见的文本控件 (UILabel、UITextView 等),其排版和绘制都是在主线程进行的,当显示大量文本时,CPU 的压力会非常大。对此解决方案只有一个,那就是自定义文本控件,用 TextKit 或最底层的 CoreText 对文本异步绘制。

尽管这实现起来非常麻烦,但其带来的优势也非常大,CoreText 对象创建好后,能直接获取文本的宽高等信息,避免了多次计算(调整 UILabel 大小时算一遍、UILabel 绘制时内部再算一遍);CoreText 对象占用内存较少,可以缓存下来以备稍后多次渲染。

1.3图片的解码

用 UIImage 或CGImageSource 的那几个方法创建图片时,图片数据并不会立刻解码。图片设置到 UIImageView 或者 CALayer.contents 中去,并且 CALayer 被提交到 GPU 前,CGImage 中的数据才会得到解码。这一步是发生在主线程的,并且不可避免。如果想要绕开这个机制,常见的做法是在后台线程先把图片绘制到 CGBitmapContext 中,然后从 Bitmap 直接创建图片。目前常见的网络图片库都自带这个功能。

1.4图像的绘制

图像的绘制通常是指用那些以 CG 开头的方法把图像绘制到画布中,然后从画布创建图片并显示这样一个过程。这个最常见的地方就是 [UIView drawRect:] 里面了。由于CoreGraphic 方法通常都是线程安全的,所以图像的绘制可以很容易的放到后台线程进行。一个简单异步绘制的过程大致如下(实际情况会比这个复杂得多,但原理基本一致):

- (void)display {

dispatch_async(backgroundQueue,^{

CGContextRef ctx =CGBitmapContextCreate(...);

// draw in context...

CGImageRef img =CGBitmapContextCreateImage(ctx);

CFRelease(ctx);

dispatch_async(mainQueue, ^{

layer.contents = img;

});

});

}

可以通过dispatch或者performSelectorInBackground或者NSOperationQueue来实现。

1.5  I/o操作

文件读写

网络

2. 避免后台加载完成多个资源之后集中到达占用UI线程的处理时间太长。(短时间内UI集中刷新)

通过NSOperationQueue来实现,将资源到UI的展现过程放在队列中逐个执行,且在每个操作完成之后进行强制等待,可以用usleep(int microSeconds)来解决。

3.线程数太多

原因:

(1)大量的任务提交到后台队列时,某些任务会因为某些原因被锁住导致线程休眠,或者被阻塞。

concurrentqueue 随后会创建新的线程来执行其他任务。

当这种情况变多时,或者 App 中使用了大量 concurrent queue 来执行较多任务时,App 在同一时刻就会存在几十个线程同时运行、创建、销毁。

CPU 是用时间片轮转来实现线程并发的,尽管 concurrent queue 能控制线程的优先级,但当大量线程同时创建运行销毁时,这些操作仍然会挤占掉主线程的 CPU 资源。

(2)线程数量达到 64个,导致也是导致卡顿的原因。

4 使用lock 时 ,不能Unlock 造成

解决方式: 使用自旋锁,递归锁。

-(void) dispatch_reentrant(void(^block)())

{

staticNSRecursiveLock *lock = nil;

staticdispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

lock =[[NSRecursiveLock alloc]init];

});

[locklock];

block();

[lockunlock];

}

dispatch_queue_t queueA = dispatch_queue_create("com.queueA", NULL);

dispatch_block_t block = ^{

//do something

};

dispatch_sync(queueA, ^{

dispatch_reentrant(block);

});

5 使用 GCDdispatch_sync 死锁卡顿

queueA—>queueB—>queueA

- (void)deadLockFunc

{

dispatch_queue_t queueA =dispatch_queue_create("com.queueA", NULL);

dispatch_queue_t queueB =dispatch_queue_create("com.queueB", NULL);

dispatch_sync(queueA, ^{

dispatch_sync(queueB, ^{

dispatch_block_t block = ^{

//do something

};

func(queueA, block);

});

});

}

解决方式, FMDB,AFNetWork 中 采用dispatch_queue_set_specific  ,dispatch_get_specific标记 队列 ,然后 进行判断处理,或给出log告警

dispatch_queue_t queueA =dispatch_queue_create("com.queueA", NULL);

dispatch_queue_t queueB =dispatch_queue_create("com.queueB", NULL);

dispatch_set_target_queue(queueB, queueA);

static int specificKey;

CFStringRef specificValue =CFSTR("queueA");

dispatch_queue_set_specific(queueA,

&specificKey,

(void*)specificValue,

(dispatch_function_t)CFRelease);

dispatch_sync(queueB, ^{

dispatch_block_t block = ^{

//do something

};

CFStringRef retrievedValue =dispatch_get_specific(&specificKey);

if (retrievedValue) {

block();

} else {

dispatch_sync(queueA, block);

}

});

6  视图的混合

当多个视图(或者说 CALayer)重叠在一起显示时,GPU 会首先把他们混合到一起。如果视图结构过于复杂,混合的过程也会消耗很多 GPU 资源。为了减轻这种情况的 GPU 消耗,应用应当尽量减少视图数量和层次,并在不透明的视图里标明 opaque 属性以避免无用的 Alpha 通道合成。当然,这也可以用上面的方法,把多个视图预先渲染为一张图片来显示。

7  主线程中UI对象创建

对象的创建会分配内存、调整属性、甚至还有读取文件等操作,比较消耗 CPU 资源。尽量用轻量的对象代替重量的对象,可以对性能有所优化。

比如 CALayer 比 UIView 要轻量许多,那么不需要响应触摸事件的控件,用 CALayer 显示会更加合适。如果对象不涉及 UI 操作,则尽量放到后台线程去创建,但可惜的是包含有 CALayer 的控件,都只能在主线程创建和操作。

·

相关文章

  • iOS - 界面优化

    APP的界面优化 什么样的界面让你觉得需要被优化呢?就是界面会卡顿咯。 下面介绍 卡顿原理 卡顿检测 实战 1、界...

  • iOS 底层原理:界面优化

    界面优化无非就是解决卡顿问,优化界面流畅度,以下就通过先分析卡顿的原因,然后再介绍具体的优化方案,来分析如何做界面...

  • iOS 底层原理:界面优化

    界面优化无非就是解决卡顿问,优化界面流畅度,以下就通过先分析卡顿的原因,然后再介绍具体的优化方案,来分析如何做界面...

  • iOS界面优化

    界面优化 本文主要介绍界面卡顿的原理以及优化 界面卡顿 通常来说,计算机中的显示过程是下面这样的,通过CPU、GP...

  • 界面卡顿优化

    1.除了UI部分,所有的加载操作都在后台完成。 1.1 文本计算 如果一个界面中包含大量文本,文本的宽高计算会占用...

  • 界面优化解析

    前言 我们经常在面试中,会被问及关于界面优化相关的问题,比如为什么界面会出现卡顿?如何监控卡顿?接着如何解决卡顿?...

  • iOS 界面卡顿优化

    了解界面卡顿原因后, 一些相关知识点; 知识点:日常开发中针对UITableView卡顿的优化方案有哪些?CPU部...

  • 卡顿优化

    卡顿优化 - CPU 卡顿优化 - GPU 离屏渲染 卡顿检测 耗电优化

  • iOS 界面优化方案

    本文主要介绍界面卡顿的原理以及优化 界面卡顿 通常来说,计算机中的显示过程是下面这样的,通过CPU、GPU、显示器...

  • iOS-底层原理 34:界面优化方案

    本文主要介绍界面卡顿的原理以及优化 界面卡顿 通常来说,计算机中的显示过程是下面这样的,通过CPU、GPU、显示器...

网友评论

    本文标题:界面卡顿优化

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