一,Android性能优化
为什么会出现性能问题?
有俩个方面: UI渲染绘制问题,内存问题
1. 布局优化,渲染问题
先来看看造成应用UI卡顿的常见原因都有哪些?
- 人为在UI线程中做轻微耗时操作,导致UI线程卡顿;
- 布局Layout过于复杂,无法在16ms内完成渲染;
- 同一时间动画执行的次数过多,导致CPU或GPU负载过重;
- View过度绘制,导致某些像素在同一帧时间内被绘制多次,从而使CPU或GPU负载过重;
- View频繁的触发measure、layout,导致measure、layout累计耗时过多及整个View频繁的重新渲染;
大多数用户感知到的卡顿等性能问题的最主要根源都是因为渲染性能。(Google官方说的)
解决方案:
- 从设计根本上简化页面的复杂度
- 减少布局的层级(如:线性布局 权重,约束布局)
- 使用include复用布局,使用ViewStub实现布局动态加载,使用merge合并布局
- 减少自定义View的过度绘制 onDraw()
2. 内存问题
出现问题的原因:内存泄漏,内容溢出
- 资源对象没有关闭,如游标(Cursor),File文件(io流)
- 内部类持有外部类的引用
- 单例造成的内存泄漏
- 线程导致内存泄漏 如:Handler的使用,
- bitmap使用完毕没有释放
- 注册没取消造成的内存泄漏,如 eventBus 没有解除注册
- 集合中对象没清理造成的内存溢出
- 安卓中使用了大量的Enum
- Bitmap对象的错误使用
- 加载的图片太大使用( lrucache缓存机制 )
- 对象内容过大
解决方案
解决以上问题
检测内存工具LeakCanary
二,事件分发机制
事件传递会经过 Activity -> ViewGroup -> View 三个对象。
当一个点击事件发生时,事件最先传到Activity的dispatchTouchEvent()进行事件分发,如果返回true 事件分发结束.如果返回false 则执行Activity 的 onTouchEvent(),如果返回super则执行ViewGroup的dispatchTouchEvent()进行事件分发,如果返回true 事件分发结束.如果返回false 则执行ViewGroup的 onTouchEvent()如果返回super则执行ViewGroup的onIntercepTouchEvent()事件进行是否拦截,如果需要拦截(方法返回 true),则表示当前 ViewGroup 希望处理该事件,或者不希望子 View 处理该事件,此时将直接调用 onTouchEvent 方法。如果不需要拦截(方法返回 false),则将该事件传递给子 View 的 onTouchEvent 方法。如果该方法返回 true,则表示事件已消费,此次事件分发就成结束;如果返回false则事件会一步步返回
三,View 的绘制流程
当一个应用启动时,会启动一个主 Activity,Android 系统会根据 Activity 的布局来对它进行绘制。绘制会从根视图 ViewRoot 的 performTraversals() 方法开始,从上到下遍历整个视图树,每个 View 控制负责绘制自己,而 ViewGroup 还需要负责通知自己的子 View 进行绘制操作。视图操作的过程可以分为三个步骤,分别是测量(Measure)、布局(Layout)和绘制(Draw)。
四,HashMap
HashMap 是基于 Map 接口实现的一种键-值对<key,value>的存储结构,允许 null 值,无序,线程不安全。HashMap 的底层实现是数组 + 链表 + 红黑树(JDK1.8 增加了红黑树部分)。它存储和查找数据时,是根据键 key 的 hashCode的值计算出具体的存储位置…
核心组成元素有:size(大小),loadFactor(负载因子),threshold(扩容阈值)
当两个对象的hashcode相同,会发生hash碰撞
https://www.wkcto.com/article/detail/760
四,LinkedeList和ArrayList的区别
ArrayList是动态数组结构,在访问数据读取数据时效率更高
LinkedList链表数据结构,进行增加和删除的操作时效率更高
数组查询具有所有查询特定元素比较快
第一:Java的数组中存储的每个元素类型一致,也就是说每个元素占用的空间大小相同。
第二:Java的数组中存储的每个元素在空间存储上,内存地址是连续状态的。
第三:通常首元素的内存地址作为整个数组对象的内存地址,可见我们是知道首元素内存地址的。
第四:再加上数组中的元素是有下标的,有下标就可以计算出被查找的元素和首元素的偏移量。
而插入和删除和修改比较慢
数组在内存中是一块连续的内存,如果插入或删除是需要移动内存
链表不要求内存是连续的,在当前元素中存放下一个或上一个元素的地址。查询时需要从头部开始,一个一个的找。所以查询效率低。插入时不需要移动内存,只需改变引用指向即可。所以插入或者删除的效率高。