苹果app的流畅性一般比安卓的要好的多,应该是和苹果系统的设计理念相同,早期的iphone4以前是绝对单任务,只能做一件事情,虽然增加了后台可以,音乐播放,定位等有限的服务,但是大多数普通应用切换到后台就别挂起,直到被系统杀死(10--15分钟)。一个任务当然内存利用率和cpu调度管理就要好管理多了,效率也高。app也不作为服务器,也不存在超多个socket链接的问题。当然app的性能问题和pc的应用性能问题完全不同。
app主要负责的是数据请求与展示,所以app主要是表现在数据请求方面,展示方面的也有,但是不多。
影响app性能的具体情况分下面几类情况:
1.服务器需要查询数据库,比较费时间。通常有这几种情况:服务器数据量较大,数据库的表分类不合理,数据库中的表索引设置不够好,数据库查询语句不够优化,数据库中有脏数据。
2.客户端重复发送大量重复的请求,如图片下载过程中的重复下载和代码逻辑有问题。
3.大量并发发送请求,导致部分请求超时,如有的登录成功后发送上下班状态请求,消息数量请求,金额请求等。
4.用百度代理函数批量解析步行距离,经纬度。
5.把大图片内存直接搬入内存并显示,大数据搬入内存。
6.程序出现死循环和经常刷新整个表格。
7.把所有的请求发送到一个服务器地址进行数据请求,导致服务器的处理性能下降,进而影响客户端的性能。
8.短期内收到大量push消息,不断中断用户操作,甚至导致用户短期内不能操作app。
9.由于发送请求较慢,请求页面的数据不确定,加载页面周期长,用户长时间看不到完整的页面,在切换页面前发送请求,发送成功才切换到对应页面。
下面是对以上性能问题的解决方案。
对于情况1,当然优化数据库中各个表格,对所有表格设置索引(表的索引对数据的查询影响超大),优化查询语句,抽象出查询高频率的表进行优化,去除脏数据。
情况2,用charles抓包和打印日志哪些请求出现了重复发送,消除这种不合理的逻辑和错误。
情况3,尽量或避免并发请求,能合并的请求尽量合并,如登录后需要发送的大量的请求,直接在登录时就把参数写上,登录的成功响应消息里把你需要各种结果都返回就可以了。
情况4,百度的步行距离计算代理和地址经纬解析代理都不支持瞬时大批量解析,轻者解析很费时间才得到结果,重者服务器拒绝解析或只解析一部分,所以要采用解析一个再去解析另一个的事件方式解析,防止一窝峰的整个表格的有关步行距离和地址解析的请求都一次性交给百度哥。当然也存在刚开断网进入应用,网络恢复,收到网络正常通知后立刻自动登录成功后立马去解析步行距离,百度哥告诉你联网成功,授权成功,实际上你会解析失败,不过你再去解析一次一般都可以解析成功。
情况5,你可以用UIImage *image = [AppManager resizeImage:[UIImage imageNamed:@”my_backgroud_up_6.png”] toSize:CGSizeMake(WINDOW_WIDTH, 64) scale:1];这种方式压缩显示在内存中。当然也有把大数据搬入内存的情况,一般只需要读取你用到的部分的数据就可以,只是我没有这方面的具体例子。这样就防止app内存暴涨了,当然你用完后不在使用它了把这类大的对象指针置空,让系统自己去回收估计效果更好些。
情况6,死循环要不得,进入死循环若没有能符合的跳出条件,app相当于隔屁了。所以尽量别设计这类的循环等待,若是完全的死循环,尽量用单元测试发现,解决掉它。循环刷表格要不得,要等所有数据处理完再刷整个表格([self.tableView reloadData]),当然你只是刷一行表格(如一行表格的高度和内容变更)可以用[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:self.selectedIndex inSection:0]] withRowAnimation:UITableViewRowAnimationNone];这样的刷新一行表格的局部表格刷新。若你只改变一个页面的一个内容(图像变换,标签内容)并且不影响表格,直接把它的指针设置成本面的全局变量,直接修改就可以了,也不需要刷新整个表格或单元格。若死循环刷新表格,整个程序也完了,肯本不能有这样的逻辑,发现一个干死一个。但是必定谁也不想写这样的代码,这就是写代码的目的和实际实现的处理不一致,单元测试测试达到分支覆盖就很容易发现这样的严重的bug,这类问题只所以出现,可能是逻辑设计错误,也可能是拼写错误,也可能是从其它代码拷贝来的代码没有修改或修改的不完全对。当把每个函数的圈复杂度降低到15以下,再编写测试测试用例就很容易。若一个主函数上千行,谈何单元测试。
情况7,每一个请求对应一个请求网页地址,用AFNetworking发送http请求,把请求的参数拼接到请求中如,http://test.zuixiandao.cn/fhl/phone/psy/startWorkJsonPhone.htm?cmdCode=0003&key=BF233049EC74B822EB5520A6ADA30A76&phoneId=ios_120e438f-9757-451d-b980-0d87824b02eb&visitTime=1437550879&workKey=1。服务器一个页面处理,当大量用户访问时容易出现性能问题,并且也不容易区分各个请求,导致内部逻辑超复杂。服务器的性能受到影响,当然也影响客户端的请求响应时间必然受到影响。这种每个请求对应一个子页面的方式也对各个页面状态的同步要求很高,操作数据库的并发也要控制好,幸亏有会话信息可以放在cookies里。
情况8,服务器的push分为不同类型,每次把push消息的类型发过来,客户端对高频发的消息进行按时间和类型的进行适当舍弃,如3秒内最多才能弹出一个新订单消息。若你的push录音播放很长,不拦截可能出现声音叠加的问题。还好苹果对每分钟向一个app最多推送消息有限时,导致不很明显,但是安卓这类现象是否严重。就因为苹果对每分钟push消息个数的限制,所以导致有部分push消息可能丢失。
情况9,最好先切换页面后发送请求,除非有特别的需求才需要这样做,不让让人有感觉处理慢的性能问题。当然跳到一个页面时要一个数据加载进度的动画效果,如一个人型图案的加载过程。进页面就显示一个菊花那样太不友好。
最app影响性能的都和服务器方面有关,弱网络登录这个最烦人了,所以要有自动登录超时也能进入首页,无网络也能进首页弹出黄条就可以。自动登录要根据网络通知事件来触发登录,没有网络还向服务发什么,当然发也是失败,还存在正在发送中网络正常的情况,这样也不可控,也不用浪费电量的起个定时器傻傻的等待网络事件的事情,虽然正常网络网络通知在1秒内可以收到,有的弱网络比较慢,何不由网络通知事件触发登录呢?所以收到网络通知才发起自动登录是最好的选择。这样在自动登录方面也提高性能,让用户app启动很快。