|
Android性能优化 1、UI渲染机制 - 系统通过VSYNC信号触发对UI的渲染、重绘,其间隔时间是16ms。
- 这个16ms其实就是1000ms显示60帧画面的单位时间
- 如果不能在16ms内完成绘制,那么就会造成丢帧现象。会在下个信号才开始绘制(2*16ms)—导致卡顿
布局优化 2、布局优化的思想 - 减少布局文件层级
- 使用高性能布局
3、View是什么? - View是Android系统在屏幕上的视觉呈现.
- View是一种控件
4、View是怎么绘制出来的? - View的绘制流程是从ViewRoot的performTraversals()方法开始
- measure()
- layout()
- draw()
5、View是怎么呈现在界面上的? - Android中的视图都是通过Window来呈现的(Activity、Dialog还是Toast都有一个Window)
- 然后通过WindowManager来管理View。
- Window和顶级View——DecorView的通信是依赖ViewRoot完成的。
6、View和ViewGroup什么区别? - View是所有控件和布局的父类。
- ViewGroup也属于 View,构成一种树状结构
7、视图优化的几种方法 - 减少画面绘制的时间
- 避免过度绘制
- 优化布局层级
- 避免嵌套过多无用布局
8、RelativeLayout和LinearLayout的性能差异 - 两者 layout和draw性能相等,区别在于 measure过程
- RelativeLayout对所有 子View会进行 两次measure(横向+纵向)—因为 子View间可能同时有 纵向和横向的依赖关系,所有都需要进行一次测量。
- LinearLayout会进行 一次measure,如果有 weight属性才会进行 第二次measure
9、布局的选择 - 如果不涉及到 层级深度,应该选择 高效的LinearLayout或者FrameLayout
- 涉及到层级深度时,如 ListView中更适合使用 RelativeLayout,且尽可能使用 pading代替 margin
- ConstraintLayout是性能最好的布局!
10、布局层级优化的三种方法 - include标签
- merge标签
- ViewStub
11、include标签的特点和使用方法 - include主要是用于布局重用,就不需要重复写相同的布局
- include中只支持 layout_开头的属性,如果指定了 id则会覆盖掉 所包含的布局文件根元素的id属性
//main.xml
< android.support.constraint.ConstraintLayout ...>
< include
android:id= "@+id/include"
layout= "@layout/my_include_layout"
android:layout_width= "200dp"
android:layout_height= "200dp"
.../>
< TextView
android:id= "@+id/sample_text"
... />
</ android.support.constraint.ConstraintLayout>
//my_include_layout.xml
< android.support.constraint.ConstraintLayout xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:app= "http://schemas.android.com/apk/res-auto"
xmlns:tools= "http://schemas.android.com/tools"
android:layout_width= "match_parent"
android:layout_height= "match_parent">
< TextView
android:id= "@+id/sample_text"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
.../>
</ android.support.constraint.ConstraintLayout> |
12、merge标签的作用 - merge一般配合 include标签使用,用于减少 布局层级
- 假如 include标签外层是 LinearLayout,内部布局根元素的布局也是 LinearLayout ,使用 merge能减少不必要的层级。
//需要将include所包含的内部布局的根布局使用merge标签,如my_include_layout.xml
< merge xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:app= "http://schemas.android.com/apk/res-auto">
< TextView
android:id= "@+id/sample_text"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:text= "I'm include"
app:layout_constraintBottom_toBottomOf= "parent"
app:layout_constraintLeft_toLeftOf= "parent"
app:layout_constraintRight_toRightOf= "parent"
app:layout_constraintTop_toTopOf= "parent" />
</ merge> |
13、ViewStub的作用和使用 - 轻量级组件(继承View):不可视、大小为0
- ViewStub一旦进行显示,就不存在了,取而代之的是被inflate的布局,并将ID设置为ViewStub中 android:inflateid属性所指的ID,因此两次调用 inflate方法会报错
- ViewStub还不支持 merge标签
< ViewStub
android:id= "@+id/not_often_use"
......
android:layout= "@layout/not_often_use"/> |
//1. 获得ViewStub组件
mViewStub = (ViewStub)findViewById(R.id.not_often_use); //viewstub的ID
//2-1. 显示该View的第一种方法
mViewStub.setVisibility(View.VISIBLE)
//2-2. 显示该View的第二种方法
View flateView = mViewStub.inflate();
TextView textview = (TextView)inflateView.findViewById(R.id.tv); |
14、绘制优化-优化View的onDraw方法 - onDraw中不要创建新的 局部对象— onDraw可能会频繁调用,瞬间创建大量对象和大量GC
- onDraw中不要做耗时的任务,尽量要保证 View的绘制频率60fps(每帧画面不超过16ms)
内存优化 15、内存泄漏优化 - 静态变量所导致的内存泄漏:如Activity内部静态变量持有Activity的this等
- 单例模式导致的内存泄漏:单例模式的对象中的链表等持有了 如:Activity的this指针,却没有即使释放会导致泄露,因为单例的特点是其生命周期和 Applicaiton一致。
- 属性动画不停止会导致内存泄漏:无限循环动画会持有 Activity的View,而 View持有了 Activity,最终导致泄露。解决办法是在 onDestory中调用 animator.cancel()
16、ANR是什么? - UI线程执行耗时操作会导致ANR
- 如果 BroadcastReceiver10秒没有执行完操作,就会导致ANR
17、ANR如何分析? - 只要出现 ANR,系统都会在 /data/anr/目录下生成相应的 trace.txt
- 根据内容可以分析 ANR的具体原因
18、ANR出现的几种特殊情况 - 主线程UI线程中进行 耗时操作
- UI线程和在其他线程的 耗时操作竞争同一个锁。
19、ListView/GridView的优化 - 采用 ViewHolder
- 避免在 getView中执行耗时操作
- 根据滑动状态控制任务的 执行频率,避免快速滑动时开启大量的异步操作。
- 开启硬件加速,使列表滑动更流畅。
20、Bitmap的优化 - 选择合适大小图片, 也可以在图片列表时显示缩略图,显示图片的时候使用原图
- 通过 BitmapFactory.Options对图片进行采样、
- 图片缓存-使用 内存缓存LruCache和 硬盘缓存DiskLruCache
21、线程优化 - 采用线程池,避免线程的创建和销毁带来的性能损失
- 线程池能有效控制最大并发数,避免抢占资源导致的阻塞
22、性能优化建议 - 避免创建过多的对象
- 不要过多使用枚举,枚举所占空间比整数大。少用迭代器。
- 常量使用 static final进行修饰
- 使用 Andorid特有的数据类型,如 SparseArray和Pair,性能更好。
- 适当使用 软引用和 弱引用
- 采用内存缓存和硬盘缓存
- 尽量使用静态内部类,避免由于内部类导致的内存泄露
- 使用静态方法,静态方法会比普通方法提高15%的访问速度
- 减少不必要的成员变量,这点在Android Lint工具上已经集成检测了,如果一个变量可以定义为局部变量,则会建议你不要定义成成员变量。
- 减少不必要的对象,使用基础类型会比使用对象更加节省资源,同时更应该避免频繁创建短作用域的变量。
- 对Cursor、Receiver、Sensor、File等对象,要非常注意对它们的创建、回收与注册、解注册
- 避免使用IOC框架,IOC通常使用注解、反射来实现,虽然Java已经进行了很好的优化,但大量使用反射依然会带来性能的下降。
- 使用RenderScript、OpenGL进行复杂的绘图操作。
- 使用SurfaceView代替View进行大量、频繁的绘图操作。
- 尽量使用视图缓存,而不是每次都执行inflate()方法解析视图。
22、性能优化工具汇总 - UI渲染时间工具:开发者中选择 Profile GPU Rendering(GPU呈现模式分析),选择 On Screen as bars能开启条形图。 蓝色线条为绘制的时间,要控制在绿线之下。
- 过度绘制:开发者中 Enable GPU OverDraw(开启过度绘制检查)
- 布局层级: Hierarchy Viewer,在 Android Device Monitor中使用。
- 代码提示工具:Lint
- Memory Monitor
- TraceView日志
- MAT
- Dumpsys
- Memory Info
----------------------------
原文链接:https://blog.csdn.net/feather_wch/article/details/79615455
程序猿的技术大观园:www.javathinker.net
[这个贴子最后由 flybird 在 2020-03-11 10:44:40 重新编辑]
|
|