需要使用

Android APP启动优化的简单探讨

2018-06-28  本文已影响66人  吉原拉面

  APP启动时,会出现一段时间的白屏/黑屏,主要原因就是Application在初始化的时候做了太多的工作。网上有很多关于启动优化的策略,像更改AppTheme设置window背景的方法,都是治标不治本的。这篇文章主要记录下从实质上减少Application初始化的时间的简单方法,主要思路就是异步初始化一些不那么重要的功能。

利用trace查看Application中的耗时操作

  我们首先使用Google Debug类中的方法来定位在Application的onCreate()中,那些操作是耗时的。使用方法很简单,在onCreate()前后打上标签即可。

  @Override
    public void onCreate() {
        Debug.startMethodTracing("xxxApp");
        ······
        Debug.stopMethodTracing();
    }

  然后跑一遍我们的应用,在sdcard/Android/date/应用包名目录下会生成一个“xxxApp.trace”的文件,我们可以将该文件放入DDMS打开。如果是Mac系统,DDMS可能无法使用,我们可以通过AndroidStudio右下角的DeviceFileExplorer工具,找到“xxxApp.trace”文件右键打开即可。


  我们通过按时间排序,就可以看到我们的应用中有哪些操作是耗时的。我们可以发现,像TalkingData、友盟分享、极光推送等SDK的初始化工作都是非常耗时的,我们可以考虑将其放入子线程中异步进行。至于哪些操作可以异步进行,判断原则就是:即使没有初始化完成,也不会影响APP进入主页面。所以像友盟分享、极光推送这类服务,用户不可能一进App就去立刻点击分享,也不需要第一时间接受推送通知,晚一两秒中并不会对我们应用的整体功能产生影响,所以我们可以选择将其异步初始化。
  不是耗时操作没有必要也异步进行 ,不会实质性的加快App启动,而且有时候开启一个异步线程也是需要花销的。除了代码看起来爽一点,个人觉得没啥必要。

子线程中初始化的方法

  在Android中开启一个异步操作的方法有很多,这个可以自己去研究下。推荐看下这篇文章:Android性能优化(十一)之正确的异步姿势
  我在项目中选择的是采用IntentService的方法,IntentService比较方便,start之后便不用管它了,毕竟我不需要任何回执。


@SuppressLint("Registered")
class InitializeService : IntentService("InitializeService") {

    companion object {
        const val ACTION_INIT_APP = "com.xxx.xxx.service.action.INIT_APP"

        fun start(context: Context) {
            val intent = Intent(context, InitializeService::class.java)
            intent.action = ACTION_INIT_APP
            context.startService(intent)
        }
    }

    override fun onHandleIntent(intent: Intent?) {
        intent?.run {
            if (ACTION_INIT_APP == intent.action) {
                performInit()
            }
        }
    }

    private fun performInit() {
        // 初始化友盟第三方分享登录
        UMShareAPI.get(this)
        // 初始化 JPush
        JPushInterface.init(this)
        ······
    }
}

对比优化后的数据

  这个我们主要从启动时间来判断。
1、通过之前说过的方法,利用.trace文件可以看到启动时间的差异
2、通过ADB命令:adb shell am start -W com.xxx.xxx/com.xxx.xxx.activity.LaunchActivity
*注意:请确保App未打开,利用冷启动的方式获取数据;你打开的Activity应该是标记为"android.intent.category.LAUNCHER"的Activity


其中ThisTime是该Activit启动的时间,TotalTime是包含了Application启动的时间,WaitTime是系统资源启动耗时。我们可以通过判断TotalTime是否有变小,来判断优化是否有用。

为什么选用IntentService

  有人可能觉得,既然是子线程初始化,那我用RxJava不是更简单方便吗?我一开始也是这么觉得的,直到遇到了一个坑。某些初始化工作可能需要用到handler这个东西,大家都知道,handler在子线程中使用时,是需要自己建一个Loop的,然后调用prepare()方法的,否则就会报错。但是IntentService在内部已经定义好了Loop,所以就不会出现这样的问题。当然,你也可以使用RxJava进行线程调度,但是有些初始化方法并不能简单地提取出来。

上一篇下一篇

猜你喜欢

热点阅读