专栏名称: 安卓开发精选
伯乐在线旗下账号,分享安卓应用相关内容,包括:安卓应用开发、设计和动态等。
目录
相关文章推荐
鸿洋  ·  Android | ... ·  3 天前  
stormzhang  ·  生活真的经不起考验 ·  4 天前  
鸿洋  ·  Perfetto 快速上手指南 ·  5 天前  
鸿洋  ·  Android 复杂项目崩溃率收敛至0.01%实践 ·  6 天前  
51好读  ›  专栏  ›  安卓开发精选

Android 端应用秒开优化体验

安卓开发精选  · 公众号  · android  · 2016-09-10 08:09

正文

(点击上方公众号,可快速关注)


来源:伯乐在线专栏作者 - Sunzxyong

链接:http://android.jobbole.com/84541/

点击 → 了解如何加入专栏作者


前言


最近部门内抛出了一个问题,应用启动很慢、卡图标?主要表现在中低端机型中。究其这个问题,由于对性能优化比较感兴趣,借了个低端机和一个中端机来一看究竟,对同一应用分别测了下它在中低端机的启动时间,下面为启动耗时情况:



启动了三次,基本都在4s左右。


原因


究其原因,主要因素是任务在界面绘制前过于集中化。


应用启动过程从用户点击launcher图标到看到第一帧这个过程中,主要会经过以下这些过程:


main()->Application:attachBaseContext()->onCreate()->Activity:onCreate()->onStart()->onPostCreate()->onResume()->onPostResume()


而一般我们的初始化任务主要都会集中化在Application:onCreate()方法中,这就使得初始化任务在第一帧绘制之前得完成,这就造成了卡图标、应用启动慢。那么把任务打散呢?分散在LaunchActivity中去分段初始化?还是不行的,因为界面开始绘制是在onResume()方法开始后才开始绘制,所以,得从Activity的创建过程找办法。


main->Activity创建的这个过程会经过一系列framework层的操作,这些操作都是系统自动执行的,不易进行优化,不过可以在Activity创建这个过程前后来找一些蛛丝马迹,因为Activity的创建都会辗转到ActivityThread:performLaunchActivity()这个方法中,在这个方法中可以知道这么几件事:


  1. 先通过Instrumentation:newActivity()来创建一个Activity实例

  2. 再判断Application实例是否已创建,已创建则直接返回,否则调用Instrumentation:newApplication()来创建Application实例,在这个过程中会依次执行attachBaseContext()和onCreate()方法

  3. 之后Activity:attach()方法会创建一个PhoneWindow对象,它就是界面,它有一个DecorView,调用setContentView()时会给配置DecorView,其中就会设置一个背景:



我们的View也是add进DecorView中显示,它作为RootView肯定是最先显示,所以可以给它设置个默认背景


    4. 最后依次调用Activity的onCreate、onStart等方法


措施


1、任务分级

2、任务并行

3、界面预显示


对于任务集中初始化化、耗时初始化原因导致应用在中低端机启动过慢,而Activity界面绘制的时机导致简单的将任务分给Activity初始化也不起作用,我们必须

找一个切入点


界面的创建和界面的绘制,这两个过程第一个是Application的attachBaseConte和onCreate这两个方法影响的,第二个则是Application创建一直到界面绘制


所以,可以对任务进行分级的临界点可以这样分:


1、CoreSDK——Application的创建

2、HighPrioritySDK——Activity的创建

3、LowPrioritySDK——Activity界面完成绘制

4、AsyncSDK——Activity的创建


如图:



对任务这样分级后,测了一下,应用的启动即使在低端机上,也能秒开:



分级带来的问题


正常启动过程那肯定是没问题的,不过有这么几种场景:


1、App切回后台,内存不足导致Application被回收,从最近任务列表中恢复界面时Application需重新创建

2、应用没挂起时,Push推送需从Notification跳入应用内某界面

3、应用没挂起时,浏览器外链需跳入应用内某界面


这些Case可能导致的问题是被跳入的界面使用到了未初始化的SDK,可能导致Crash或者数据异常,所以目标页面启动前必须确保SDK已经初始化,这个过程的原因是没有唤起启动页来初始化SDK,可以通过hook newActivity解决。


public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException {

    if (InitializeOptimizer.isApplicationCreated()

            && (InitializeUtil.isOuterChainIntent(intent) || InitializeUtil.isNotificationIntent(intent)) && (!InitializeOptimizer.isHighSDKInitialized()

            || !InitializeOptimizer.isLowSDKInitialized()

            || !InitializeOptimizer.isAsyncSDKInitialized())) {

        InitializeOptimizer.setApplicationCreated(false);

        intent.addCategory(InitializeUtil.INITIALIZE_CATEGORY);

        return (Activity) cl.loadClass(InitializeOptimizer.getLaunchClassName()).newInstance();

    }

    InitializeOptimizer.setApplicationCreated(false);

    return super.newActivity(cl, className, intent);

}


专栏作者简介( 点击 → 加入专栏作者 


Sunzxyong :热衷移动Android开发

打赏支持作者写出更多好文章,谢谢!




------------------ 推荐 ------------------


范品社推出了十几款程序员、电影、美剧和物理题材的极客T恤单件 ¥59.9、两件减¥12、四件减¥28,详见网店商品页介绍。

网店地址:https://fanpinshe.taobao.com/

淘口令:复制以下红色内容,然后打开手淘即可购买

范品社,使用¥极客T恤¥抢先预览(长按复制整段文案,打开手机淘宝即可进入活动内容)