『一篇就够了系列』Android App优化知识点全收藏

  1. include、merge、ViewStub

  2. ConstraintLayout 降低层级

  3. RelativeLayout和LinearLayout的选择:

RelativeLayout层级少,但是子View会调用两次onMeasure;LinearLayout层级多,会增加内存,并且如果使用weight属性也会调用两次onMeasure。在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout.

  1. SurfaceView 或 TextureView

工具


  1. uiautomator.bat

分析xml布局方式;

  1. monitor.bat

绿: 表示该 View 的此项性能比该 View Tree 中超过 50% 的 View 都要快;例如,代表Measure 的是绿点,意味着这个视图的测量时间快于树中的视图对象的 50%。

黄: 表示该 View 的此项性能比该 View Tree 中超过 50% 的 View 都要慢;

红: 表示该 View 的此项性能是 View Tree 中最慢的;

2. 【内存管理】

====================================================================

内存模型


JVM:方法区、虚拟机栈、本地方法栈、堆、程序计数器

内存抖动


内存分配速度大于回收速度。

比如拼接string字符串,换成stringbuffer或stringbuilder。

回收算法


标记清除算法 Mark-Sweep

复制算法 Copying

标记压缩算法 Mark-Compact

分代收集算法

工具


  1. profiler

  2. MemoryAnalyzer

  3. leakcanary

解决内存泄漏的方法


  1. 单例

  2. handler

  3. 静态变量

  4. 匿名内部类

  5. 注册与取消注册

  6. 定时任务

  7. 资源关闭

  8. 属性动画

  9. webview内存泄漏(开个新进程)

  10. 其它注意事项:

基本数据类型用static final 替换static;

使用for循环还是迭代器Iterator对比:

采用ArrayList对随机访问比较快,而for循环中的get()方法,采用的即是随机访问的方法,因此在ArrayList里,for循环较快

采用LinkedList则是顺序访问比较快,iterator中的next()方法,采用的即是顺序访问的方法,因此在LinkedList里,使用iterator较快

从数据结构角度分析,for循环适合访问顺序结构,可以根据下标快速获取指定元素.而Iterator 适合访问链式结构,因为迭代器是通过next()和Pre()来定位的.可以访问没有顺序的集合.

而使用 Iterator 的好处在于可以使用相同方式去遍历集合中元素,而不用考虑集合类的内部实现(只要它实现了 java.lang.Iterable 接口),如果使用 Iterator 来遍历集合中元素,一旦不再使用 List 转而使用 Set 来组织数据,那遍历元素的代码不用做任何修改,如果使用 for 来遍历,那所有遍历此集合的算法都得做相应调整,因为List有序,Set无序,结构不同,他们的访问算法也不一样.(还是说明了一点遍历和集合本身分离了)

3. 【网络优化】

====================================================================

解决方案


  1. API接口设计:多个api得到的数据合并一个api得到;

  2. GZip压缩request和response;

  3. Protocol Buffer代替json;

  4. 获取图片的URL告知服务器所需图片的宽高;

比如根据不同网络条件返回不同大小图片;采用webp;

  1. 大文件下载断点续传;

  2. 增量包:bsdiff和bspatch;

  3. 网络请求的数据进行缓存;

比如将网络请求得到的数据放入数据库,每次加载页面先从数据库获得,等获取到网络数据后更新UI和数据库;

  1. JobScheduler在wifi情况下进行下载任务,比如广告等;

5.0后用JobScheduler,8.0后用WorkManager。

  1. webview加载,涉及到前端html页面优化;

专项:弱网优化


先缓存请求,等网络情况好时再通过JobScheduler发送请求。比如点赞。

通过OkHttpClient配置cache,当手机没有联网的时候,就可以直接从缓存中加载数据。还可以设置读、写、连接超时。

4. 【应用瘦身】

====================================================================

  1. AndResGuard资源文件瘦身;

  2. lint去除无用资源:Analyze > Run Inspection By Name > unused resources;

  3. proguard:开启 minifyEnabled 混淆代码,可以压缩文件,使用 shrinkResources 去除无用资源;

  4. 图片:

使用svg格式(xml格式);

tinypng压缩;

webp格式;

  1. 插件化

  2. 只保留一个cpu架构的so文件:armeabi-v7a

  3. 去除多语言;

  4. 去除第三方库,比如rxjava等;

5. 【启动优化】

====================================================================

1. 启动黑白屏


1. 方法1:自定义背景图 + 全屏

黑白屏是因为系统在创建进程的时候

我们首先想到的方案是用一张图片代替黑白颜色,并且为了更好的效果可以设置为全屏显示。

首先定义一个BaseTheme:

··· xml

···

然后定义一个启动页的style,继承自BaseTheme。

这个方案的缺点是从全屏到非全屏页面(如MainActivity)会有一个抖动的过程。

2. 方法2:透明 + 禁用窗口预览动画

这种方案适用于启动页无需耗时的场景,如果启动需要一段时间的话,这段时间对用户来说会以为点击了桌面图标后会出现没有反应,体验不好。

3. 方法3(推荐):自定义背景图+透明状态栏

综合方法1和方法2的缺点,我们提出一种方案,那就是通过自定义背景图片+将系统状态栏透明化的方案。

这种方案既不会产生抖动问题,也不会点击桌面图标后出现的无反应场景。

2. 启动耗时检测


启动分为冷启动和热启动。

冷启动就是进程被杀,或者第一次启动;

热启动就是Activity被回收,但是Application仍存在,无需重新创建,对应的进程还在。

1. 命令行

命令行:adb shell am start -S -R 3 -W com.androidwind.androidquick.sample/.SplashActivity

-S表示每次启动前先强行停止,-R表示重复测试次数。

运行结果如下:

Stopping: com.androidwind.androidquick.sample

Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.androidwind.androidquick.sample/.SplashActivity }

Status: ok

Activity: com.androidwind.androidquick.sample/.SplashActivity

ThisTime: 2851

TotalTime: 2851

WaitTime: 2894

Complete

缺点:

1. 某个Activity可能需要经过多个Activity跳转后才能到达,需要叠加这些Activity启动的时间;

2. 统计时间不准确,比如只计算了Activity的启动和初始化时间,并未统计等待时间;

3. 统计的Activity需要设置或者android:exported=“true”;

2. 写一个计时工具TimeUtils

主要区分热启动和冷启动的耗时算法。

冷启动 = application启动时间 + 热启动时间;

热启动指Activity的启动时间。

3. 第三方工具nimbledroid

https://nimbledroid.com/

3. 优化方案


App加载过程比较复杂,我们客户端开发中能够控制的优化点是Application和Activity。

懒加载

  1. Application:SDK

尽量将第三方的SDK进行延迟初始化,用到的时候再去加载。

  1. Application:static变量

比如一些static对象,如果初始化时间较长,而启动时暂未用到,可以考虑放到后续第一次使用的时候初始化。

  1. Activity:viewstub

ViewStub在使用到的时候才会加载。

总之目的就是减少View层级,减少View绘制时间。

比如使用ConstraintLayout。

  1. Activity:Fragment

lazyfragment

开启子线程处理

Thread、ThreadPool、AsyncTask、IntentService、HandlerThread、RxJava等。

注意子线程不能阻塞主线程,比如sharedpreferences加载大容量sd卡文件则会造成主线程阻塞。Thread的join和FutureTask的get也会阻塞主线程。

6. 【电量优化】

====================================================================

工具


Battery-Historian

耗电定位


CPU 处理

定位

网络

图像

==========================================================

优化


优化的途径主要体现在以下几个方面:

  1. 尽可能降低 CPU、GPU 的功耗。尽量少用 定时器。优化 I/O 操作。ART替换Dalvik,减少CPU工作,减少空间,节省电量

不要频繁写入小数据,而是积攒到一定数量再写入

读写大量的数据可以使用 Dispatch_io ,GCD 内部已经做了优化。

数据量比较大时,建议使用数据库

面试宝典

面试必问知识点、BATJ历年历年面试真题+解析

学习经验总结

(一)调整好心态
心态是一个人能否成功的关键,如果不调整好自己的心态,是很难静下心来学习的,尤其是现在这么浮躁的社会,大部分的程序员的现状就是三点一线,感觉很累,一些大龄的程序员更多的会感到焦虑,而且随着年龄的增长,这种焦虑感会越来越强烈,那么唯一的解决办法就是调整好自己的心态,要做到自信、年轻、勤奋。这样的调整,一方面对自己学习有帮助,另一方面让自己应对面试更从容,更顺利。

(二)时间挤一挤,制定好计划
一旦下定决心要提升自己,那么再忙的情况下也要每天挤一挤时间,切记不可“两天打渔三天晒网”。另外,制定好学习计划也是很有必要的,有逻辑有条理的复习,先查漏补缺,然后再系统复习,这样才能够做到事半功倍,效果才会立竿见影。

(三)不断学习技术知识,更新自己的知识储备
对于一名程序员来说,技术知识方面是非常重要的,可以说是重中之重。要面试大厂,自己的知识储备一定要非常丰富,若缺胳膊少腿,别说在实际工作当中,光是面试这一关就过不了。对于技术方面,首先基础知识一定要扎实,包括自己方向的语言基础、计算机基础、算法以及编程等等。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》
点击传送门,即可获取!

其是现在这么浮躁的社会,大部分的程序员的现状就是三点一线,感觉很累,一些大龄的程序员更多的会感到焦虑,而且随着年龄的增长,这种焦虑感会越来越强烈,那么唯一的解决办法就是调整好自己的心态,要做到自信、年轻、勤奋。这样的调整,一方面对自己学习有帮助,另一方面让自己应对面试更从容,更顺利。

(二)时间挤一挤,制定好计划
一旦下定决心要提升自己,那么再忙的情况下也要每天挤一挤时间,切记不可“两天打渔三天晒网”。另外,制定好学习计划也是很有必要的,有逻辑有条理的复习,先查漏补缺,然后再系统复习,这样才能够做到事半功倍,效果才会立竿见影。

(三)不断学习技术知识,更新自己的知识储备
对于一名程序员来说,技术知识方面是非常重要的,可以说是重中之重。要面试大厂,自己的知识储备一定要非常丰富,若缺胳膊少腿,别说在实际工作当中,光是面试这一关就过不了。对于技术方面,首先基础知识一定要扎实,包括自己方向的语言基础、计算机基础、算法以及编程等等。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》
点击传送门,即可获取!

  • 29
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值