一、RecycleView 优化
RecycleView在开发时可以考虑以下优化的方案:
1. 数据处理和视图加载分离
a. 数据的处理逻辑尽可能放在异步处理,onBindViewHolder方法只做数据填充视图的操作。
b. 对ItemView设置监听器,不要对每一个Item都调用addxxListener,可以考虑公用一个xxListener,根据ID的不同来操作,优化了对象的频繁创建带来的资源消耗。
2. 数据加载优化
a. 分页拉取远端数据,并对拉取下来的数据进行缓存,尽可能提升二次加载速度。
b. 对于新增的或者删除数据通过 DiffUtil 进行局部数据的刷新,尽量不进行全局数据刷新。
c. 对于使用库版本在25.1.0及以上的时候使用Prefetch功能。
3.布局优化
a. 减少布局层级,简化ItemView。
b. 如果Item高度是固定的话,可以使用RecycleView.setHasFixedSize(true)来避免requestLayout浪费资源。
c. 如果多个RecycleView的Adapter是一样的,比如嵌套的RecycleView中存在一样的Adapter,可以通过设置RecycleView.setRecycleViewPool(pool),来共用一个RecycleViewPool。
二、项目启动优化
我们知道有很多第三方组件(包括App应用本身)都在 Application 中完成初始化操作。但是在 Application 中完成繁重的初始化操作和复杂的逻辑就会影响到应用的启动性能。
通过分析一下,我们可以知道还是有机会优化这些工作以实现冷启动的性能改进的,分析后发现影响冷启动时间的常见问题如下:
- 复杂繁琐的布局初始化
- 阻塞主线程 UI 绘制的操作,如 I/O 读写或者是网络访问.
- 其它占用主线程的操作
我们可以根据这些组件的轻重缓急之分,对初始化做一下分类 :
- 必要的组件一定要在主线程中立即初始化(入口 Activity 可能立即会用到)
- 组件一定要在主线程中初始化,但是可以延迟初始化。
- 组件可以在子线程中初始化。
在进行优化的时候,需要注意以下几种情况:
- 放在子线程的组件初始化建议延迟初始化,这样就可以了解是否会对项目造成影响!
- 将需要在主线程中初始化但是可以不用立即完成的动作延迟加载(初始化放在 Application 中统一管理为妙,不建议放在Activity里面)
- 可以尝试将常见的组件库,例如 Bugly,x5内核初始化,SP的读写,友盟等组件放到子线程中初始化。(子线程初始化不能影响到组件的使用)
在优化好启动时间后,我们就可以在针对闪屏页的时间,进行调整优化,具体公式为:闪屏页展示总时间 = 组件初始化时间 + 剩余展示时间。
推荐的优化方案:
1). 合理的使用异步初始化、延迟初始化、懒加载机制。
2). 提前加载SharePreferences
3). 类加载优化:提前异步执行类加载。
4). 合理使用IdleHandler进行延迟初始化。
三、常见的内存问题及优化方案
1. 内存泄漏
内存泄漏的定义是:内存中存在已经不再使用,但是并未回收的对象。表现的现象为:内存出现抖动和可用内存逐渐变少。存在的危害是:会造成内存不足,GC频繁,甚至出现OOM。
常见引发内存泄漏的主要情况有如下情况:
1. static 关键字修饰的成员变量
核心点:被static修饰过的成员变量的生命周期 = 应用程序的生命周期。
泄漏原因:若被static修饰的成员变量引用短生命周期的实例,则容易出现该成员变量的生命周期 > 引用实例生命周期的情况,当引用实例需结束生命周期销毁时,会因静态变量的持有而无法被回收,从而出现内存泄露。
解决方案:
a. 尽量避免static成员变量引用资源消耗过多的实例(若需引用Context,则尽量使用Application的Context)。
b. 使用弱引用WeakReference代替强引用持有实例。
经典案例 ==》单例模式
核心点:单例模式 其生命周期的长度 = 应用程序的生命周期
泄漏原因:若1个对象已不需再使用 而单例对象还持有该对象的引用,那么该对象将不能被正常回收 从而 导致内存泄漏
解决方案:单例模式引用的对象的生命周期 = 应用的生命周期。 或者编写代码保证在合适的时机释放资源。
2. 非静态内部类/匿名类
核心点:非静态内部类默认持有外部类的引用,可能会导致外部类对象无法释放,造成内存泄漏。
解决方案:使用静态内部类。
经典案例 ==》Runnable、AsyncTask、Thread、Handler 等类
3. 资源使用后未关闭
泄露原因:对于资源的使用(如 广播BraodcastReceiver
、文件流File
、数据库游标Cursor
、),若在Activity
销毁时没有及时关闭或注销这些资源,则这些资源将不会被回收,从而造成内存泄漏。
解决方案:在Activity
销毁时 及时关闭 / 注销资源
2. 内存抖动
核心原因:频繁创建大量、临时的小对象。
排查方向:优先寻找循环或者频繁调用的地方进行排查。
优化方案:避免创建大量、临时的小对象。