天天看点

安卓性能优化总结

​​最全的性能优化点总结:... 4​​

​​零、       启动优化... 4​​

​​1、项目背景... 4​​

​​2、     检测启动时间... 4​​

​​3、打印启动时间... 4​​

​​4、优化理念:... 4​​

​​5、启动时透明页优化:... 5​​

​​6、multidex优化... 5​​

​​7、多进程时,防止sdk多次初始化... 5​​

​​8、最终结果:... 5​​

​​一、       内存优化... 6​​

​​1、     项目背景... 6​​

​​2、性能优化的理念... 6​​

​​3、了解对象之间的引用关系和对象大小的占用... 6​​

​​4、了解android中经常造成内存泄漏的点... 6​​

​​(1)、耗时任务:网络请求、属性动画、timer 6​​

​​(2)、handler 6​​

​​(3)、匿名/非静态内部类... 7​​

​​(4)、单例、applicationcontext 、threadlocal等... 7​​

​​(5)、webview内存泄露... 7​​

​​(6)、资源未及时关闭... 7​​

​​5、内存溢出问题... 7​​

​​6、内存抖动的问题... 7​​

​​7、体验优化... 7​​

​​8、内存视图查看;... 8​​

​​9、了解对象产生和分配过程;... 9​​

​​10、对象创建的过程中代码执行顺序... 9​​

​​11、sp文件的优化... 9​​

​​12、详细的优化过程... 9​​

​​13、优化结果... 10​​

​​二、       安装包瘦身... 10​​

​​三、       网络优化... 13​​

​​四、       第三方库的一些简单替代方案... 14​​

​​五、       图片加载库的问题以及性能比较... 16​​

​​1、问题背景:... 16​​

​​2、图片库测试结果:... 17​​

​​3、测试过程... 17​​

​​4、使用建议:... 17​​

​​六、       锁的优化synchronized和lock. 17​​

​​锁的优化方向:... 17​​

​​延伸单例写法推荐... 18​​

​​七、       mvp设计模式的弊端及解决方案(重点) 19​​

​​mvp存在的问题:... 19​​

​​(1)      首先是设计思路问题... 19​​

​​(2)      过多的present和model的问题... 19​​

​​(3)      内存泄露的问题... 19​​

​​(4)      解决办法... 19​​

​​(5)      此mvp设计总结:... 25​​

​​九、view绘制方面的优化... 25​​

​​(1)多嵌套问题:... 25​​

​​(2)各种控件性能比较:... 25​​

​​(3)使用占位符viewstub:... 25​​

​​(4)结语:... 25​​

​​十、一些知名的内存管理监测软件... 26​​

​​(1) leakcanary. 26​​

​​(2) koom... 26​​

​​十一、数据加密优化... 26​​

​​项目背景:... 26​​

​​优化方案:... 26​​

​​对称加密... 26​​

​​非对称加密... 27​​

​​散列算法:... 27​​

​​常用的加密方案:... 27​​

​​总结:... 27​​

​​十二、修正一下编程思想!面向对象 or 面向过程... 27​​

​​(1)面向对象开发和面向过程开发... 27​​

​​十三、架构方面:对app代码业务逻辑的一些设计思考... 30​​

​​1、项目背景:... 30​​

​​2、优化思路:... 30​​

​​3、详细内容,举例说明... 30​​

​​十四、数据库和高并发优化... 33​​

​​1、问题背景... 33​​

​​2、     高并发优化... 33​​

​​3、数据库优化... 33​​

​​十五、android特有的库和一些代码基础写法... 33​​

​​​​

最全的性能优化点总结:零、 启动优化

19公司里的一个项目,是一个第三方库特别多的app,会启动10个广告sdk、若干游戏sdk。初期都是在application里面直接初始化的

adb shell am start -w 包名/界面名                                  

安卓性能优化总结

oncreate、onresume等方法的耗时,尤其是初始化许多sdk 的方法(可使用aop方法、或者system时间相减,都可以;aop的包有applyplugin: 'android-aspectjx' implement 'org.aspectj:aspectjrt:1.8.+')

筛选启动时必须加载的sdk,其他的则放在子线程里面或者延时加载

把十几个要实例化的sdk分成三部分:先加载、延迟加载、异步加载、懒加载

先加载:因为首页有开屏广告,所以开屏广告的sdk必须有先加载

安卓性能优化总结

把各种库分成四种情况都是为了尽可能提高启动速度;

设置透明主体或者提早设置背景页面;都比较常规的方法,我选择了设置背景页面,给用户一个第一时间我就打开了app的感觉,否则会有一种卡顿的感觉

这个问题,在我们第三方sdk特别多的项目里尤为明显;体积小的apk一般就一个dex;开启多dex打包之后,就会产生很多dex文件;这个我用的主流的方法;异步加载其他dex;最恶心的过程就是手动分包,因为要保证启主dex体积比较小;能快速的加载出来,然后其他dex就放在子线程里边去加载

项目当中有一些音乐播放是夸进程,所以需要防止一些sdk多次初始化,这个比较简单,不贴代码里额

启动时间节省了一半以上

一、          内存优化

这个是15年银行的电商app项目,由于当时的项目前后端整体设计不是特别完善;整个的图片的处理都是在客户端完成的;包括加水印、压缩等等,而且图片不管是上传还是下载的都是高清原图,所以对app的性能是极大的考验;也是当时的app前后端设计不是特别合理,所以草导致了这个问题,不过也因此我锻炼了内存优化的能力和知识

两个强引用对象之间有引用关系,且其中一个对象生命周期较长,在15年优化一个项目的时候,许多人会手动调用system.gc(),这是性能优化一大禁忌;简单说我们创造对象是可回收的环境,让gc需要的时候自己就来处理垃圾收,本身垃圾回收的操作也是消耗性能的;这就像在一个小区里边,有专门收垃圾的车进来,你只需要把垃圾放到垃圾桶中,其他的就不要管了,不要自己频繁的去呼叫垃圾车来收垃圾;一旦来收垃圾的时候你自己也要停止工作(stop the world),大家都耽误事儿

按默认开启指针压缩来算,除了基本数据类型之外,其他类型是占用四个字节,也就是多写一个成员变量对象就增大四个字节;和这个成员变量有没有具体引用到那个对象没关系,只要是生命了就会多占用内存

还有第三方控件,那个放在后面常见的内存泄漏情况有:

解决办法就是及时解除强引用关系、把指针置空、及时停止耗时任务;或者用弱引用设置指针关系

handler一般是因为有延时任务,message里有个handler类型的target变量,这个就是引用handler的成员变量,所以如果延时任务不结束,那么handler所在对象就无法被回收掉。解决办法就是重写handler或者及时清除延时任务

这个就是内部类对象会持有外部类的引用,所以如果非静态内部类对象/匿名对象的成生命周期较长就会影响外部类对象的回收。

其实都是强引用关系和生命周期不同造成的的;解决办法就是用弱引用和及时解除他们的关系,因为一般单例、appcontext、threadlocal不会被干掉,生命周期比较长,所以就只能及时解除关联关系,把变量的引用置空就可以了

这个问题存在很久了,也没注意现在有没有被修复,主要原因是webview内核webkit和application有注册关系,所以一定要反注册,解决办法就是activity关闭之前,获取webview的父布局,然后remove掉webview,然后停止webview的一些方法、清楚历史清除views。最后再执行webview.destroy();

这个就是io流、file文件流、sqlite这些只用完毕时候要及时关闭

比如:eventbus,广播,以及contentprovider等等,都需要在ondestory里面反注册;我写的mvp模式的evm也需要反注册;

这个在android中,一般就是bitmap或者视频之类的容易造成内存溢出,内存溢出分两种,一种是直接溢出,一种是内存泄露累积起来的内存溢出,都是堆空间里满了造成的oom;bitmap就是压缩图片,bitmap的大小就是和像素的面积和每个像素点的色位决定的;这个就是按照bitmap要显示的实际大小进行压缩;一般就是计算压缩比例,然后抽取bitmap图片;

这个就是要优化程序了,现在这个问题出的情况比较少,也是15年的时候优化过,里面有一些比较大的对象进行频发的创建和销毁就会造成内存抖动,其实就是会频繁的出发gc操作;延长这个对象的生命周期或者优化这个对象的大小

这一般是整体架构的问题,加载一些图片的时候,就算手机内存足够大,但是网速也限制图片的下载速度,尤其是在一些列表图片功能里,体验就会很差,如果图片体积很小,那给人的感觉就不同;现在都比较正规了,这个问题也几乎没有了

学会使用android profiler,先手动gc,然后根据类名寻找对象是否存在,就可以查找到android对象是否内存泄漏了;除了内存外,cpu、网络、能耗都可以查得到

安卓性能优化总结

搜索对象是否存在

安卓性能优化总结

可分配在堆内存、栈内存;堆内存中还包括新生代、老年代,还要根据对象的大小去判断;

静态变量、静态代码块,代码块;构造方法、父类和子类中这几种情况的执行顺序,了解这些会有助于了解代码的执行过程和内存的分配

其实就是同步还是异步的问题,想要性能好肯定选择异步,然后合并多次commit();

commit(同步)apply(异步)

替代方案:mmkv 腾讯出的,从15年开始一直在微信上使用,可见其性能得到了考验

(1)、选择最优图片加载库:格比较了各种图片库的优缺点和性能问题,选择一个最稳定的,最终确定了使用frsco(选择过程后面,解析第三方图片库有讲解)

(2)、清除项目里手动gc操作

(3)、解除activity里的网络请求操作和主acitvity的匿名回调对象的关系;采用统一的回调方式,这样网络请求的耗时操作就不会影响正常的acitivty对象回收了

(4)、针对项目里的内存抖动问题,尽量延长对象的声明周期、压缩对象的体积,目的旨在减少system.gc出来工作的次数

(5)、bitmap优化,设置bitmap.config为argb_4444或者565;再就是根据控件实际显示的大小,计算压缩比例,创建像素合适的bitmap;最后就是及时释放资源执行recycle()方法并且置空;因为项目里有bit加水印的操作,所以需要自己处理一下

(6)、写法上的优化,把加载fragment的写法从add改成replace。activity里边减少成员变量,有一些只有个点击事件,并无其他操作,所以不必在activity创建成员变量,少写一个成员变量就节省了4个字节的空间量变引质变。直接再xml文件里写onclick方法,而且效率要远远比先findviewbyid然后再setonclicklistener高出很多很多;再就是尽量减少布局的嵌套、多用include和megre、viewstub

(7)、测试一些父控件的执行效率,效率最差的relativelayout,linearlayout和fragmentlayout性能相差无几;那时候constraintlayout还未流行起来,所以未做处理,一些简单布局优先使用linear/framelayout;

(8)、用android studio逐个activity检查内存泄漏的情况;检查过程就是先打开此activity页面,然后关闭,然后手动调用几次gc操作;最后查看此activity对象是否还存在,如果还存在就表示有内存泄漏,再逐个排查,多数都是匿名对象造成的

(9)、检查有和单例、applicationcontext扯上关系的对象,这些都是内存泄露潜在的点,所以要重点检查

(10)、检查handler的延时任务,那时候还不会弱引用,所以只是手动的在activity关闭的时候,自己手动清除handler的延时任务

(11)、把项目里的listview替换成recyclerview,recyclerview性能比listview好很多,也是经过测试的;

(12)、app创建线程池,来统一管理一些定时任务,包括轮播、短信验证码等。

(13)、recyclerview、listview之类的控件,在滑动的时候要停止图片的加载

项目从原来的崩溃率特别高,降到非常低,崩溃情况不会出现了

一、安装包瘦身

也是16年银行的直销银行项目,android包体积过大,其中也主要是因为加入人脸识别、地图等各种so库造成的

so文件过多,按照cpu架构有个多个类型,这个看app的使用潜在人群,如果是手机一般只用v7就可以,如果是pad那就用x64,x86之类的,总之要具体选择

安卓性能优化总结

当时的项目用的是v7

2、 默认国际化:关掉默认国际化

安卓性能优化总结

因为android打包成apk之后,apk里会有一个叫resources.arsc的文件,里边都是res/values文件夹下文件生成的,而且默认会生成很多国家的语言像这样

安卓性能优化总结

我们只要设置只支持中文或者英文就可以了

3、 一些图片转换成webp格式,当然了压缩的时候肯定会有是真的情况,这个就看你怎么取舍了,如果失真不明显那么能压缩还是要压缩的;一些小的图标可以使用vector矢量图,这个体积也是比png小很多,而且不需要进行适配,矢量图可以根据实际需求显示大小,不想使用png还要区分各种屏幕大小

安卓性能优化总结

矢量图vector,现在新建个项目android的logo就是vector矢量图

安卓性能优化总结

4、 常规手段:混淆(代码混淆、资源文件混淆)、去除无用文件;下图是去处无用文件的,混淆我就不解释了

安卓性能优化总结

5、 优化结果:项目体积减小了很多,主要是so文件的功劳,so文件的选择对于android体积减小是最客观的,其他的作用都不是太大,但是积少成多效果很明显的;上面的优化方案:资源文件的混淆和vector矢量图的优化方案在当时的项目是没用上的,那时候还不知道这些,但是借这次机会也总结出来分享给大家

一、网络优化

1、这个我觉得没什么太好的办法,首先根据当前网络情况来处理数据,如果是网络比较差的时候,可疑更换网络协议,直接使用tcp、mqtt之类的;如果是http那么打开

gzip 压缩;使用ip地址免解析等等

2、 自己创建数据解析和压缩的字典;

3、 数据缓存、连接池复用、合并请求

二、第三方库的一些简单替代方案

这虽然是一个很好用的库,但是有很严重的性能问题,对于我这种代码洁癖的人来说不可忍受;他提供的库虽然很丰富,但是要遍历一个类里的所有方法,然后识别出需要的,尤其是在activity里边,本身activity的的方法和变量都特别多,无形之中就是消耗的许多性能;解决方案比如可以这样写:

安卓性能优化总结

想在哪里接受数据,就在哪里执行注册,比如在acitivty中:

安卓性能优化总结

当然,这里面也有内存泄露的问题,匿名内部类对象;此处只做案例,如果想切换线程,也可在里面创建一个handler,就可以做到eventbus的全部工作,但是性能会比它好很多

注解去实例化view控件也是存在这个问题;会遍历所有的成员变量;并且会额外产生类,并且包含你所有的控件成员变量,相当于acitivty站用内存相当于翻倍了,多声明一个成员变量就多占用四个字节的空间,而且还会多创建一个对象,16个字节;如果页面比较多累计起来不仅消耗内存还消耗性能,像xuitls、buffterknife等等都是相同的原理

可疑自己写一个简单,只要能符合当前app的业务需求,只是不满足,也可以继续改进满足,比如下面的例子:当然,如果你的业务中特别复杂,第三方库了的所有功能基本都能用到,那还是直接用他们的比较好;这个就是开发方便和性能之间的一个平衡。

安卓性能优化总结

使用方法:

安卓性能优化总结

1、 结语:大多数app的业务没那么复杂,第三方库提供能的功能可以说异常的丰富;对于大部分项目来说过于丰富,很多功能是用不上的,所以就造成了额外的性能消耗;当然自己写的时候要注意内存泄露的问题,如果对内存泄漏问题掌握的不够自信,那老老实实用第三方库也是可以的

一、图片加载库的问题以及性能比较

这个也是15年银行的电商app项目性能优化的时候,碰到的问题,因为内容比较多,所以单拿出来说一说;比如imageloader性能最好,但是有很严重的内存泄露的问题;fresco 会彻底解决内存的问题,但是使用起来却没有imageloader流畅;picsso 在我看来和imageloader差不多;现在最长的是glide,因为glide有一些自动管理图片加载的机制和context的生命周期的管理;在15年的时候,列表类的图片,在滑动的过程中要自己手动停止图片加载功能;这个gilde都帮我们处理了;还有context的声明周期管理,避免的内存泄露的产生

fresco稳定性最好;glide体验最流畅也没有内存泄露的问题;有自动的生命周期管理,imageloader、xutils、piacsso基本被淘汰了;现如今反编译很多知名厂商app、使用的图片库都是glide

当时是写了一个相册的功能,分别使用以上图片加载库去加载相册,然后反复打开关闭相册页面,记录打开次数、流畅度;测的最终上面的结论

个人建议:xuitls3、imageloader、picasso可以抛弃了;imageloader有很严重的内存泄露问题,而且也不更新了xutils和picasso估计也有,这是机制的问题;毕竟网络请求是一个耗时的 操作,都需要传入context上下文

建议使用glide:理由

(1)、绝大多数主流app,反编译这些源码,使用的都是glide;可见它的受欢迎程度

(2)、它自有的context生命周期管理,可以在activity/frgment页面关闭的时候glide可以在第一时间检测到,停止图片的下载,这样就防止了内存的泄露和cpu资源的消耗;

(3)、glide支持gif图片

(4)、支持配合滑动列表滑动时候停止加载图片

(5)、最后说fresco,这是个压箱底的东西,如果glide都不能满足的时候,再把它拿出来;fresco用c写的库,把图片数据存储在了ashmem区域,这样就不占用jvm堆内存了,所以说它的终极大招;但是他使用起来却没有前面几个java的体验感更加流畅,所以把它放在最后的选择;

至于其他的一些缓存机制、缓存策略这些,比如缓存的是压缩后的图片还是原图,这个区别不大,而且都可以手动修改设置,所以这些机制就不做参考了

二、锁的优化synchronized和lock

这个就简单一说吧,要了解synchronized的锁升级过程、粗化、消除等等;lock里的抽象队列同步器,cas自旋、用户态、内核态、操作系统互斥量;内容较多,可以自行学习,我就简单说下结论:并发量小就用sync关键字,并发量大就使用lock

1、 尽量减小加锁部分代码的执行时间,因为可能有其他线程在等待,等待的线程越多,最后的那个线程能执行到加锁里的内容的时间越长

2、 减小锁的力度或者是范围:比如map中的concurrenthashmap,它是一个线程安全的集合,锁只是锁住了单独的桶,就算是两个线程同时写入数据,只要hash值算的下标不再同一个位置就不会有影响;

安卓性能优化总结
安卓性能优化总结

锁分离:把两种互不影响的操作,分别加锁,比如linkedblockqueue

安卓性能优化总结

我们看到针对不同的操作,分别用不同的锁;

单例推荐静态内部类单例,即使线程安全的也是懒加载,而且不需要枷锁,所以性能上会节省一丢丢;

安卓性能优化总结

七、吗mvp设计模式的弊端及解决方案(重点)

从最开始接触mvp模式,不断的思考和改进mvp的写法,以达到最好的要求,代码量小,解耦;业务逻辑清晰,尝试过很多次,今年自己要写开源项目,所以干脆就根据多年积累重新整理了一个mvp的写法,已经放到github上了,欢迎交流

是按照业务就划分view还按照接口去划分view;如何去划分persent;present和model还有view之间是不是要一一对应的关系;其实这就牵扯了activity;如果按照接口去划分view那么view直接定义成responsedata类型的返回值就行了;有几个接口就定义多少个view;另外一种方式就是按照业务去划分,比如登录的业务可能包括登录、验证码、短信登录、忘记密码,这些操作,把这些业务都写到一个logincontract里边,再分别定义其他各种业务,我是比较推崇后者的

如果一个页面中,只有一个接口,一个简单的功能,也需要额外写一个present、model、view吗?这样就很冗余;也不利于开发速度;如果这样的activity还特别多,那就是写一个actvity就要写一个view和present,显然这样代码量太大太蠢了

我们知道网络请求是耗时操作,一旦网络不好的情况用户又关闭了activity,此时这个activity是无法被回收掉的这就造成了内存泄露问题。activity一般是内存占用大户,虽然可以用弱引用去处理,但是弱引用也会额外的创建对象,会增大内存的占用

创建evm中间类,让present和view、model中间,不产生强引用关系,所以也就不会产生内存泄露的问题;再就是present和modle都可以自由定义,想定义几个就定义几个,都可以通过evm中间类进行关联,而且采用的是反射的方法,只获取接口,所以对性能无影响,不像eventbus和butterknife那样要遍历所有的方法或者变量,而且如果view已经回收,则会生成一个临时该接口类型的对象,不需要是否为空判断

安卓性能优化总结

代码是:

/**

 * description:

 * author: tianhonglong

 * new date: 2021/7/9

 * version: v 1.0

 */

publicclass evm {

    private evm() {

    }

    private map<string, easyview> views =new hashmap<>();

    private map<string, easypresent>presents = new hashmap<>();

    private <t extends easyview> t getview(class<t>clazz) {

        easyview easyview =views.get(clazz.getsimplename());

        if (easyview == null) {

            try {

                return clazz.newinstance();

            } catch (illegalaccessexception e){

                e.printstacktrace();

            } catch (instantiationexception e){

            }

        }

        return (t) easyview;

    private <t extends easypresent> tgetpre(class<t> clazz) {

        easypresent present =presents.get(clazz.getsimplename());

        if (present == null) {

                t t = clazz.newinstance();

               presents.put(clazz.getsimplename(), t);

                return t;

        return (t) present;

    private void managerview(easyview easyview,boolean registerornot) {

        class[] classes =easyview.getclass().getinterfaces();

        for (class clazz : classes) {

            if(easyview.class.isassignablefrom(clazz)) {

                if (registerornot) {

                    views.put(clazz.getsimplename(),easyview);

                } else {

                   views.remove(clazz.getsimplename());

                }

    public static void register(easyvieweasyview) {

        evm.ins().managerview(easyview, true);

    public static void unregister(easyvieweasyview) {

        evm.ins().managerview(easyview, false);

    public static <t extends easyview> tgetv(class<t> clazz) {

        return evm.ins().getview(clazz);

    public static <t extends easypresent>t getp(class<t> clazz) {

        return evm.ins().getpre(clazz);

    private static class innerclass {

        private static evm easypresent = newevm();

    private static evm ins() {

        return innerclass.easypresent;

}

在basectivity中使用:

安卓性能优化总结

而且只搜索存在接的接口,一个类的接口不会太多,所以不会影响性能

安卓性能优化总结

定义一个基类接口

​写一个logincontract,把和登录有关的view和present都定义在里边

安卓性能优化总结

loginactivity中,

安卓性能优化总结

在看看present代码:优雅的很

安卓性能优化总结

1、 彻底解除view、present、model之间的关联,其中model、view、present各自想写几个就写几个,通过evm中间类关联,都可以互相调用;

2、 解决了view的内存泄露问题,不产生直接强引用就能互相调用,所以不会影响内存回收;

3、 只需要关注业务的开发,针对接口去设计model

安卓性能优化总结

4、 只需要在present里面处理业务流程,actvity处理业务的发起和结果接受;modle按照接口文档傻瓜式写上就可以了,也不需要加各种try catch;底层会帮业务处理好,直接回调给当前的view

九、view绘制方面的优化

优化别人代码的时候,布局文件中最常见的就是过多嵌套问题,很多子空间就可以实现的,很多人非要加个父控件,比如linearlayout、relativelayout等等,再就是用merge可以减少嵌套,由于空间渲染计算是递归形式,在以前的老旧机型里,只要嵌套7层layout,就会有明显的卡顿产生,但是如果同级别里,就算是14层也不会有任何问题,所以某些界面使用linearlayout并不会比relativelayout带来更多控件层级时,优先考虑linearlayout;;

性能最差的是relativelayout;如果linearlayout和framelaout都满足的情况下,优先排除relativelayout; 如果再复杂就是使用google新出的constraintlayout; 还有recyclerview的性能都要比listview好很多,比如加载fragment除了用懒加载外,replace也add要节省内存

在一些界面里的控件,需要最开始状态是view.gone;但即使是view.gone,这个控件依然会执行各种实例化方法创建对象占用内存,只是最后没有通过wms渲染在手机屏幕上而已,viewstub是一个轻量级的view;使用viewstub后,那么原来的控件就相当于懒加载了,只有用户用手操作让它显示的时候才会去加载,如果一直不要求显示那就永远不会加载;只是会多一个轻量级的viewstub

写代码的过程中,有许多不经意的点都是可以节省内存的,只要节省每一处的内存和cpu的使用;累计起来就是一个好的项目;如果对内存不省吃俭用,累积起来的内存泄露造成的oom是最难解决和优化的;

十、一些知名的内存管理监测软件

就是用weakreference和referencequeue

这两个类的机制,来检查内存是否泄露的;可疑帮助你快速定位内存泄露的点;但是不能帮你解决内存泄露的问题,只是帮你发现问题

快手自研oom解决方案。效率据说比leakcanary好的多,具体还没使用过,推荐给大家;

十一、数据加密优化

这个是20年优化的一个项目,因为在银行和金融app行业经验丰富一些,所以在一些非银行类app中的数据安全这一块,做的有问题;直接用非对称去加密、解密数据;这个性能是有很大问题的;

要把对称加密和非对称加密结合起来使用,通信数据要用对称加密去加密和解密,然后把对称加密的钥匙,用非对称加密进行加解密,然后把加密后的钥匙拼接在隐藏在数据中,这样在安全性不变的情况下,性能会大大的提升

<col>

名称

密钥长度

运算速度

安全性

资源消耗

des

56位

较快

3des

112位或168位

aes

128、192、256位

成熟度

安全性(取决于密钥长度)

rsa

dsa

只能用于数字签名

ecc

低(计算量小,存储空间占用小,带宽要求低)

速度

sha-1

md5

md5:比如用户输入的密码,用md5进行加密,直接存储在后台的就是md5数据,再就是校验数据的完整性

sha-1:一般签名密钥里东西

对称加密:加密基本数据,因为性能比非对称加密好的多

非对称加密:加密对称加密的钥匙,组合使用,这样安全性即达到了非对称级别,性能也上去了;

总结:

md5校验完整性+对称加密加密全部数据+非对称加密对称加密的密钥

最常用的就是md5+rsa+aes

十二、修正一下编程思想!面向对象 or 面向过程

这个是优化现在公司里的一个项目;虽然java是面向对象语言,但是在很多项目中的同事,仍然使用面向过程的思维模式开发;举个简单的例子,比如曾经做的人脸识别app中,有这样一个场景,在人脸识别拿到数据之后,产生了一个用户对象,里面包含了用户的起止时间用户身份;先看面向过程写法,极其简单的一个案例:

安卓性能优化总结

再看面向对象写法:

安卓性能优化总结

可读性和简洁性对比明显;就是在写代码的时候要分清业务流程和业务细节;此处的流程就是此人是否可通行,业务细节就是判断此人是否可通行的过程;这部分代码不要出现在流程里边

上面只是写了个简单的例子,我们项目中实际的是否允许通过的判断要复杂的多,包括多分组、多时段、所以判断过程很复杂代码量也不少

十三、架构方面:对app代码业务逻辑的一些设计思考

这个是优化了代码的业务逻辑,其中最典型的人脸识别页面activity,有7500+行代码,里面包含了各种业务包括:数据的同步、ui的显示(识别结果展示)、人脸认证的过程(包括人脸、温度、口罩、距离识别、硬件接口回调等等),还包括一些业务细节的处理比如最后两次人脸是否同一个人,wifi状态监听的等等吧;

按照业务分类,可分为ui部分、验证流程部分、验证细节处理部分、面向对象部分;拆分成三个activity,原来是一个faceverifyactivity,如今拆分成facebusinessactivity,faceuiactivity,其中继承关系:

faceverifyactivity 继承facebusinessactivity继承 faceuiactivity

faceuiactivity的功能应该只包含ui部分,和人脸认证没有任何逻辑关系,只是提供了人脸结果出来的时候,可能需要显示的各种dialog、或者其他ui

facebusinessactivity里面包含最后两次是否同一个人的判断方法,数据同步的方法等等

faceverifyactivity:纯粹是业务流程的判断,然后根据每次判断的结果,来调用faceuiactivity和facebusinessactivity的方法,这样整个业务逻辑就清晰很多

由于原项目代码量特别大,所以也不可能全部贴出来;所以此处举例说明:

首先是uiactivity,定义了一些需要显示的ui对话框之类的

安卓性能优化总结

其次是业务activity,定义了开门、数据同步,是否同一个人等等

安卓性能优化总结

最后是主流程activity:纯粹的流程判断

安卓性能优化总结

1、 在案例中每个页面30~40行代码,如果不拆分,不按照面向对象写那么在一个页面中就会有110行的代码,这只是案例,真实项目中把案例代码量扩充70倍,才是我们项目中的实际代码,一个activity有7000多行代码,谁不头疼?拆分后分成三部分,每部分就两千多行,而且除了faceverifyactivity外,其他几个类中方法之间没有调用,都是单独的业务方法,以后修改起来会简单容易的多;这其实也是属于模块化思想,按类型分类,就是目的都是为了让代码单一、简洁、易修改、便于扩展;

十四、数据库和高并发优化

首先说惭愧;这个问题不是我实际工作的经验;这个是去某家公司面试的时候,面试官问的问题,问的高并发的数据存储和数据优化,回答的不是太好,也确实没这方面经验,本着不会就要学习的态度,还是研究了很多文章和代码,在此也分享出来,在此直说客户端如何解决

问题1:消息从未读到已读,这个消息如何发送? 如果是实时的,那一条已读消息要发送给一万个人,如果一万个人同事读了这条消息,就会发生一万个人同事给一万个人发消息,并发量可想而知;这个解决办法就是降低频率,是否已读,10秒钟才去刷新一次,这样就大大降低了消息的并发数

问题2:一个人接受到不同人的多条信息时,建立缓冲区。,合并多条消息给一人,甲乙丙丁同时给a发送消息,那么就建立缓冲机制,把甲乙丙丁合成一条消息,这样最后技术层面a只收到一套消息,总之目的就是降低并发数量;

数据库的并发优化和im通信类似,数据里边有事务,其实就相当于建立缓冲区合并多条数据,然后开启专门的现成去执行数据库的操作

android中的sqlite是默认开启事务的,就算只是只有一条数据的插入更新也会帮你开启事务,所以当并发量大的时候,把多条执行语句放在一个事务里,这样就提高了性能,不用每次都打开关闭事务;

索引就是把数据库里的数据,建立一个目录,在查找的时候不用一页一页去查了,索引一般是平衡树结构;简单说就是利用算法和数据结构提高效率,但是貌似在数据量特别大的时候,维护索引也会产生不小的开销;

比如有些数据的存储和同步不需要知道返回结果,这样建立一个线程池去执行这些任务,这样就不会影响主线程操作

十五、常见的anr操作

原理也很简单,系统服务ams和wms会检测app响应时间,也就是本地的applicationthread是否会及时的给ams和wsm发送binder信息,如果超过一定的时间未发送,系统就会认为你卡住了;就会提示无响应,因为通过applicationthread给系统服务发送信息都是通过主线程来执行的,所以一旦在主线程中执行耗时操作就会引起anr

十六、android特有的库和一些代码基础写法

1、

对象的序列化android 特有的parcelable比serializable的性能好

2、 android特有的集合:在数据量小的情况下使用sparsearray、arraymap代替java集合

3、 map的多种遍历方式,那种效率最快

4、 在写基础库的时候,尤其是处理数据,线程安全的情况下使用stringbuilder、线程不全的情况下使用stringbuffer

5、 根据数据存储和使用情况来判断使用链表集合还是数组集合

6、 尽量使用基本数据类型,比如int类型的成员变量一共就占用四个字节的堆空间。如果用integer除了所在类中成员变量的四个字节外,还会有integer对象的16个字节;

7、 循环中减少对变量的重新计算

比如:for(int i = 0; i &lt; list.size(); i++) 改为for(int i = 0, len = list.size(); i = len; i++)

8、 避免使用二位数组,数据比较特殊,不管你是否存入对象,数组创建的那一刻,内存已经消耗掉了,数组里每个指针占用四个字节;不算对象头和数组长度,一个长度为10的二维空数组创建的那一刻就是占用10*10*4 = 400个字节;还不算对象头类指针数组长度;像arraylist也一样,因为都是数组

9、 json序列化性能对比:数据量小就用gson,数据量大就用阿里巴巴的fastjson

作者:田洪龙