前置知识
- 有Android开发基础
前言
性能优化一词相信大家都经常听到,今天我们就简单的来认识以下性能优化,了解做性能优化的必要性以及优化的分类。
为什么要进行性能优化
下图来自于 FaceBook,这是他们对 Android 性能以及用户日活跃度两个指标的统计。我们可以清晰的看到性能和用户日活是正相关的,软件的性能越好,那么表现出来的业务数据也会更好。所以说,我们技术上的指标提升,同时也会使得业务指标的提升,这是业务方面我们需要做性能优化的理由。
而从另一个角度——硬件发展的角度来看,我们会发现当代的芯片的性能提升速度其实在是不断的下滑的。无论是 Intel 和 ADM 的x86架构的芯片,还是 ARM 的arm 架构的芯片,近年来都呈现放缓的趋势。
即使ARM平台由于其架构和工艺双重不断迭代的缘故,其性能在最近几年间提升的速度很快,最明显的表现就是我们一代代的手机的处理器之间增强的幅度很大,但是这也无法阻止技术变更的规律,它的优化幅度就是在不断的变弱,直到最后的挤牙膏。
当然多核技术也对芯片性能带来了优化,但是同时也对芯片大小和电池性能有限制,所以这项技术也是处于瓶颈了。
综上所述,从硬件发展的角度来看,硬件的发展逐渐趋于停止,我们需要做好软件的性能优化,才能在未来硬件发展停滞的时候,做好用户体验的提升。
所以说,无论是从业务指标或者是硬件能力上来讲,我们去做好性能优化都是很必要的。
什么是性能优化
性能优化是什么?其实就是要实现三点:快、稳、省。
- 何为快?
快就是指,打开App时候很快、打开页面很快、播放视频音乐很快以及滑动得很顺畅。这些都被称之为快,核心要义是指:用户很快能接收到系统的回馈 - 何为稳?
稳的意思是,系统很稳定。软件不会出现异常的bug、不会闪退和ANR,这些都是稳的体现。 - 何为省?
省的意思是空间和数据的节省。具体体现为安装包的大小、安装后使用所占用的存储空间大小以及网络数据的读取量大小。把这些都给省下来就是省的要义。
基于以上的三点目标,我们其实可以将性能优化简单的分为以下四类。
- 流畅性优化,响应快,流畅性高
- 资源优化,最小的负载带来最大的收益
- 稳定性优化,稳定的实现功能,减少不必要的打断
- 系统级优化,充分挖掘系统的资源,让APP在有限的资源内能够有更高的流畅性。(较难,较为底层)
上述四类优化在此暂不做详细阐述,上述的稳定性优化是等级最高的,上线之前必须排除所有已知的bug,这是众所周知的。而流畅性优化是较为常见的、开发者闷都会去完善的优化。下面我们就来举一些例子,看一下我们之前的哪些文章中提到的属于流畅性优化。
- 隐性的滑动冲突
在与滑动冲突的首次邂逅一文中,我们提到了一个较为隐性的滑动冲突,就是下面左图中的上下滑动突变为左右滑动的问题。而解决之后,在同一方向任意滑动都不会出现滑动突变的问题了,这大大的提高了滑动的流畅性,同时也是实现了交互的稳定性。
- 启动白屏
我们知道,如果我们未对自己的项目的APP做白屏优化,那么在APP首次启动的时候,都会出现一个短暂的白屏。这是因为APP首次开启主进程,且通过各类初始化的时候,是需要一定的执行事件的,而这个执行时间就显现出来就是白屏效果。
而一个没有实际画面的白屏,对于用户来说是一种卡顿、不流畅的体现,所以各大厂家会使用 APP 的 Logo 或者是其他动画形式的做一个启动页。将这种启动页代替白屏就可以在感器上减少卡顿感。
下面展示我做的一个启动页效果,更详细的文章在极简抖音中的优化点
- 启动速度优化
上述的启动页是可以让用户减少卡顿感,但这终究是一个视觉上面的欺骗,但是在数据指标上面,我们的启动时间没有真的减少。对于小型APP来说,未优化的时候启动时间不会很长,但是对于大型APP来说,就会有很大的影响了,让用户等一个启动页等超过2s,用户也会觉得卡顿的。
所以,我们需要做好启动优化。启动优化的点很多,但是总结为一点就是:减少不必要的初始化。我们可以对各进程做分类加载,把一些加载异步化等等。
下面附上我做不同进程区别加载的操作,详细解释依旧在极简抖音中的优化点一文中。
public class App extends Application { private static Context context; private static String sCurProcessName = null; private String processName; private String packageName; /** * Set the base context for this ContextWrapper. All calls will then be * delegated to the base context. Throws * IllegalStateException if a base context has already been set. * * @param base The new base context for this wrapper. */ @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); processName = getCurProcessName(base); packageName = getPackageName(); } private boolean isMainProcess() { return !TextUtils.isEmpty(packageName) && TextUtils.equals(packageName, processName); } @Override public void onCreate() { super.onCreate(); context = getApplicationContext(); if (isMainProcess()){ MMKV.initialize(this); MMKV.mmkvWithID("MyID", MMKV.SINGLE_PROCESS_MODE, GlobalConstant.MMKV_KEY); //载入Dokit监测 new DoKit.Builder(this) .productId(context.getString(R.string.value_dokit_pid)) .build(); //使用订阅索引,加快编译速度 EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus(); // 抖音授权 String clientkey = context.getString(R.string.value_client_key); DouYinOpenApiFactory.init(new DouYinOpenConfig(clientkey)); //初始化 MyUtil.initialize(this); //设置UI工具 RxTool.init(this); //网络缓存 RetrofitCache.getInstance().init(this); }else { QbSdk.initX5Environment(getContext(), new QbSdk.PreInitCallback() { @Override public void onCoreInitFinished() { // 内核初始化完成,可能为系统内核,也可能为系统内核 } /** * 预初始化结束 * 由于X5内核体积较大,需要依赖网络动态下发,所以当内核不存在的时候,默认会回调false,此时将会使用系统内核代替 * @param isX5 是否使用X5内核 */ @Override public void onViewInitFinished(boolean isX5) { LogUtil.i("是否使用腾讯内核:" + isX5); } }); } //设置打印开关 LogUtil.setIsLog(true); //注册Activity生命周期 registerActivityLifecycleCallbacks(ActivityUtil.getActivityLifecycleCallbacks()); } public static Context getContext() { return context; } private static String getCurProcessName(Context context) { ... } private static String getProcessName(int pid) { ... } } 复制代码
- 多进程预加载
在Android里面,每打开一个进程就会默认去跑Application
类,所以如果我们在使用的时候才去开启进程,就会使得页面首次开启的时候较为缓慢。为解决这个问题,我们可以让进程在后台预先开启,这样就能减少我们首次开启多进程功能的启动时间了。
下面示例是后台启动多进程的代码,详情请参阅极简抖音中的优化点一文。
//在对应的生命周期启用即可 private void startHideService(){ Intent intent = new Intent(this, PreLoadService.class); this.startService(intent); } private void stopHideService(){ Intent intent = new Intent(this, PreLoadService.class); this.stopService(intent); } 复制代码
上述这些都是我们有实现的流畅性优化点,它可以能让我们的APP使用体验更加的极致,同时也是对我们技术的考验。
相信大家学到这里,会了解到了为何需要性能优化且什么是性能优化了,今天的分享就到此结束