精华内容
下载资源
问答
  • App启动时间优化 一、首先我们需要清楚App的主题加载 你的App的主题位于 res/values/styles 我们点击Light主题进去,会发现此主题位于 app/build/intermediates/exploded-oar/...
  • APP启动速度非常重要,APP启动速度慢,可能会造成用户体验不良好,尤其是在最近用Android studio之后,如果长时间不打开app,启动速度就会特别的慢,下面我们一起探讨一下影响app启动速度的原因,以及解决方案。...
  • Android 冷启动,优化app启动速度(视觉上提高启动速度)
  • 引言通常来讲,咱们都会将本身的产品与同类的产品... APP启动速度优化2. APP UI流畅度优化3. 内存优化4. APP瘦身5. 电量优化javaAPP启动速度优化(1)初识启动方式APP启动的方式分为3种:;冷启动、热启动、温启动。-...

    引言

    通常来讲,咱们都会将本身的产品与同类的产品进行个比对,不可避免的会去作些性能优化,以达到赛过其余产品的优点。因此,今天咱们就来说讲性能优化的方方面面。css

    一般咱们所说的性能优化,会从如下几个方面入手:

    1. APP启动速度优化

    2. APP UI流畅度优化

    3. 内存优化

    4. APP瘦身

    5. 电量优化java

    APP启动速度优化

    (1)初识启动方式

    APP启动的方式分为3种:;冷启动、热启动、温启动。

    -冷启动:应用程序从头开始,须要作大量的工做,耗费的时间最多。

    -热启动:系统会把你的活动放在前台,活动有驻留在内存中,好比按了home键。相对于冷启动,开销较低。

    -温启动:用户退出应用程序,随后又从新启动,可是活动的进程是有驻留在后台的,好比按了back键退出应用。android

    (2)为何白屏?启动慢?

    一、Application的onCreate流程,通常来讲,在这个方法会进行大量的通用组件的初始化工做;

    二、Activity的onCreate流程,布局太过复杂,致使UI布局渲染耗时,影响启动性能。

    (3)解决办法

    第一种方法:主题切换。这是治标不治本的问题,只是改善了交互的友好性。

    主题theme_bg:其中android:opacity=”opaque”参数是为了防止在启动的时候出现背景的闪烁。web

    android:opacity="opaque">

    android:src="@mipmap/ic_launcher" />

    android:src="@drawable/launch_screens" />

    android:src="@mipmap/ic_launcher" />

    样式style:数据库

    在manifest中,将启动页的主题设置为咱们定义的主题AppTheme.Launcher:缓存

    android:theme="@style/AppTheme.Launcher">

    在MainActivity中,切换回原来的主题:性能优化

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    //切换回原来的主题,必须在setContentView前调用

    setTheme(R.style.AppTheme);

    setContentView(R.layout.activity_main);

    }

    第二种方法:异步加载、延迟加载、多进程时按照进程区分进行一些初始化工做等。

    主要有如下几种状况须要延迟加载:markdown

    该段文本转载自:http://www.jianshu.com/p/f5514b1a826c

    1.数据库及IO操做都移到工做线程,而且设置线程优先级为THREAD_PRIORITY_BACKGROUND,这样工做线程最多能获取到10%的时间片,优先保证主线程执行。

    2.流程梳理,延后执行;

    实际上,这一步对项目启动加速最有效果。经过流程梳理发现部分流程调用时机偏早、失误等,例如:

    更新等操做无需在首屏还没有展现就调用,形成资源竞争;

    调用了IOS为了规避审核而作的开关,形成网络请求密集;

    自有统计在Application的调用里建立数量固定为5的线程池,形成资源竞争,在上图traceview功能说明图中最后一行能够看到编号12执行5次,耗时排名前列;此处线程池的建立是必要但能够延后的。

    修改广告闪屏逻辑为下次生效。

    3.其它优化;

    去掉无用但被执行的老代码;

    去掉开发阶段使用但线上被执行的代码;

    去掉重复逻辑执行代码;

    去掉调用三方SDK里或者Demo里的多余代码;

    信息缓存,经常使用信息只在第一次获取,以后从缓存中取;

    项目是多进程架构,只在主进程执行Application的onCreate();

    具体操做:在启动页Activity或ManiActivity的onCreate中进行延迟操做网络

    getWindow().getDecorView().post(new Runnable() {

    @Override

    public void run() {

    myHandler.post(mLoadingRunnable);

    }

    });

    相关连接:

    架构

    展开全文
  • 在项目的持续迭代中,总是会引入很多第三方的SDK,初始化时,都建议在Application的onCreate方法中做初始化,这就导致了App启动时,因初始化消耗大量的时间,给用户带来很不优化的体验。 针对这一问题,进行逐步攻破...

    在项目的持续迭代中,总是会引入很多第三方的SDK,初始化时,都建议在Application的onCreate方法中做初始化,这就导致了App启动时,因初始化消耗大量的时间,给用户带来很不优化的体验。
    针对这一问题,进行逐步攻破解决

    一,统计应用的启动时间

    1. 通过Adb命令启动应用获取App启动的耗时:adb shell am start -W com.xx.xx/.MainActivity
      运行adb命令后会在dos窗口输入应用启动的大概耗时时间
      ThisTime :最后一个Activity启动时间
      TotalTime:一系列Activity启动时间
      WaitTime :总启动时间,包含在冷启动时,需要加载App信息到内存的时间
    2. 使用Debug.startMethodTracing()/Debug.stopMethodTracing()统计方法耗时
      例:
    public void onCreate(){
         super.onCreate();
         File file = new File(Environment.getExternalStorageDirectory(),“app.trace”);
         Debug.startMethodTracing(file.getAbsolutePath());
        //中间SDK初始化
       init();
       test();
       Debug.stopMethodTracing()}
    

    添加Debug.startMethodTracing()方法后启动App,会生成一个app.trace的文件,使用:adb pull /storage/emulated/0/app.trace命令把文件pull到电脑上,拖动到AndroidStudio中,即可预览,查看onCreate中所有方法的耗时。

    1. Trace.beginSection(“Launcher”)/Trace.endSection()方法
      例:
    public void onCreate(){
         super.onCreate();
       Trace.beginSection("Launcher");
        //中间SDK初始化
       init();
       test();
       Trace.endSection()}
    

    使用方法和Debug.startMethodTracing()类似,也会生成一个文件,放到AndroidStudio中查看应用方法的耗时
    4)最普通的统计方法,声明全局变量,在onCreate()放启动时赋值,然后在每个方法之前和之后打印当前时间,计算时间差,统计相关SDK初始化的耗时

    二,初始化耗时优化的方法

    1)延迟初始化

    在初始化时,并不是所有的第三方库都需要立即进行初始化(比如,网络请求库,不会立即使用的三方UI库,层级很深的引用库),这些都是需要耗费启动时间的,针对这些库,我们可以选择性的进行延迟初始化,通过在Applicaton中添加
    registerActivityLifecycleCallbacks() 的注册监听获取当前的Activity对象,判断当Activity进入启屏页时,再调用需要延迟初始化的SDK进行初始化,这样就可以达到一定的优化(市面上大部分的App启屏页都会停留2~3秒的时间)利用这段时间,可以初始化很多的第三方库。
    注:延迟初始化,仅初始化立即需要的对象,不要创建全局静态对象,而是移动到单例模式,其中应用尽在第一次访问对象时初始化它们。

    2)异步初始化

    所谓异步初始化,就是在Appliction中开启子线程,把一些不依赖主线程的初始化工作放到子线程中进行初始化,减少主线程的工作,从而达到优化启动速度的效果。
    注:
    异步线程中使用的api不能创建Handler
    不能有UI操作
    对异步要求不高
    在使用异步初始化时,需要确定SDK能不能异步优化,执行的方法是否有先后顺序

    3)空闲时初始化

    通过:Looper.myQueue().addIdleHandler监控当前内存是否空闲进行初始化

    Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
            @Override
            public boolean queueIdle() {
                SDKConfig.INSTANCE.initSdk();
                return false;
            }
        });
    

    4)避免重复的初始化

    随着业务的不断增多,很多应用都使用了多进程的方式开辟更多的内存空间来提升用户体验,在Android中当开启多个进程时Application的onCreate方法就会走多次,在做SDK初始化时,如果不做处理,就会导致SDK被初始化多次,导致资源的浪费和时间的占用,为了避免这个问题,需要在onCreate方法中,获取当前进程名,进行针对性处理

    5)布局加载速度优化

    App启动时,看到的第一个界面,也是优化点之一,如果布局加载的时间很长也会影响到App启动的速度,Android中所有的布局大都是xml的形式实现,在加载到屏幕上时根据布局的复杂程度需要耗费很多的时间,针对这一点,可以使用google官方提供的AnsyncLayoutInflater进行异步优化加载,提升速度或者使用使用阅文集团的开源库:“X2C”进行布局加载的优化,从而进一步提升App的启动速度。
    做完如上优化后,App的启动速度会得到质的提升,如需更进一步优化:

    • 去除不在使用的库,优化过时的库
    • 仅仅提取使用的代码
    • 选用更小的外部库
      如上优化仅个人理解,如有错误或其他方法,请补充优化。
    展开全文
  • 启动过程产品逻辑 从用户点击桌面图标到首页完全加载,需要经过三个页面,第三步中,如果用户是安装或升级后第一次打开应用,则显示引导页,否则显示广告页。 透明页 点击应用图标后系统会有3秒的响应时间,...

    启动过程产品逻辑

     

    从用户点击桌面图标到首页完全加载,需要经过三个页面,第三步中,如果用户是安装或升级后第一次打开应用,则显示引导页,否则显示广告页。

    透明页

    点击应用图标后系统会有3秒的响应时间,这段时间系统好像无响应,实则在为应用准备运行环境,打开一个无边框的窗口,这个窗口默认为白色,现在App调整成了透明,然后会初始化各个三方库,向网络请求应用图标序号。

    闪屏页

     

    闪屏页是启动过程中最为复杂的一步,它包含:检查权限并弹窗提醒,提前请求首页数据,启动引导页或广告页

    检查权限

    进入闪屏页,首先会按顺序检查四个权限,分别是读写手机文件的权限、获取本机号码本机唯一标识码的权限、手机录音的权限、获取手机定位的权限。如果其中一个对话框拒绝授权,会再弹出一个对话框劝用户授权,如果还不授权则退出APP。详细逻辑如图。

    请求首页数据

    如果请求成功会缓存请求结果,如果请求失败会取上次缓存的请求结果

    启动引导页或者广告页

    在启动引导页或广告页之前,会先停顿2秒,然后根据是否是第一次进入应用决定是进引导页还是广告页

    引导页

     

    如上图所示,引导页需要向右划4下,并点击立即体验进入应用

    广告页

    安装后第二次打开应用会显示广告页,广告页会根据上一次拉取的图片进行显示

    首页

               

    启动过程代码逻辑

    App

    这里是整个应用的入口类,在这个对象创建时,会初始化SmartRefreshLayout下拉刷新组件,然后会在onCreate生命周期回调方法中执行如左图逻辑,大部分是初始化业务SDK

     

    上图是App类中的全局字段和全局方法

    ChangeIconActivity

     

    WelcomeActivity

     

    其中SP是手机存储中的SharedPreference XML文件

    AdvertNewActivity

     

    GuideActivity

     

    启动原理

     

     

    • 应用的启动分为两部分工作,第一部分工作由Android操作系统完成,包括以下三项:
    1. 加载并启动应用程序
    2. 为即将启动的APP显示一个空白窗口
    3. 创建应用进程
    • 第二部分有APP的进程自己完成,包括以下六项任务:
    1. 创建应用进程底层对象
    2. 启动JVM主线程
    3. 创建应用入口Activity对象
    4. 将XML中的文本转化为可运行的View对象
    5. 布局各个控件
    6. 实际绘制各个控件

    当入口页面第一帧绘制完毕,操作系统就会把绘制好的画面切换进屏幕的最上层,然后用户就可以开始与APP交互。

    从进程角度分析,应用的启动涉及四个进程,分别是Launcher进程(实际就是系统桌面APP),system_server进程(承载了大部分的系统服务功能),Zygote进程(用于创建新进程),App进程。

    当用户点击桌面图标,实际是点击Launcher应用上的带图标的按钮,触发启动。

    从类和方法调用角度分析如下图所示:

     

    图中长方形代表类,线上的文字代表函数调用,序号代表调用顺序,其中可以直接优化的就是Application类的OnCreate方法(如图中序号5位置)和Activity的onCreate方法如图中序号9的位置。

    优化措施

    启动窗口背景优化

    如启动原理部分介绍,系统在启动APP进程前会先打开一个空白窗口,之前APP已将此窗口设置为透明,但为了给用户更快的响应速度和更好的启动体验,可以将此窗口设置为与启动页同一张图片,这样由这个窗口到启动页虽然是两个页面,但是显示一张图,用户是感知不到切换的。具体做法见这里的启动主题优化部分。

    参考案例:百度地图Android APP。

    Application类的优化

    可以将APP启动过程中的retrofit,友盟,市民卡web容器(含x5内核),通付盾,无痕埋点的初始化过程放在子线程中进行。还可以优化精简逻辑。

    闪屏页优化

    (1)Activity合并,是否可以把换图标的ChangeIconActivity的逻辑、广告页AdvertNewActivity的逻辑、引导页GuideActivity的逻辑合并进闪屏页的WelcomeActivity的逻辑,从而减少Activity切换的时间开销。

    (2)网络请求优化,是否可以把部分启动过程中的网络请求放在首页

    (3)闪屏页在跳转引导页或广告页之前会故意停留2s多,可以看是否可以去掉,如不可以去掉,也可以动态计算停留时长,就是把停留时长减去之前启动逻辑(包括网络请求返回数据)的时长

    引导页放在首页上

    如上图所示,示例APP:抖音:

    闪屏页申请权限的对话框放在首页进行

    这样用户可以在前台处理授权对话框,首页在后边可以同时处理大量的网络访问和页面逻辑,两边同时进行。示例APP:抖音

    监控措施

    adb命令

    adb shell am start -S -R 10 -W com.hfi.hangzhoubanshi/ .home.activity.ChangeIconActivity  

    其中-S表示每次启动前先强行停止,-R表示重复测试次数。每一次的输出如下所示信息:

    Stopping: com.example.app  
    Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.app/.MainActivity }  
    Status: ok  
    Activity: com.example.app/.MainActivity  
    ThisTime: 1059  
    TotalTime: 1059  
    WaitTime: 1073  
    Complete  

    其中TotalTime代表当前Activity启动时间,将多次TotalTime加起来求平均即可得到启动这个Activity的时间。

    缺点:应用的启动过程往往不只一个Activity,有可能是先进入一个启动页,然后再从启动页打开真正的首页。某些情况下还有可能中间经过更多的Activity,这个时候需要将多个Activity的时间加起来。

    将多个Activity启动时间加起来并不完全等于用户感知的启动时间。例如在启动页可能是先等待某些初始化完成或者某些动画播放完毕后再进入首页。使用命令行统计的方式只是计算了Activity的启动以及初始化时间,并不能体现这种等待任务的时间。

    没有在AndroidManifest.xml对应的Activity声明中指定<intent-filter>或者属性没有android:exported="true"的Activity不能使用这种命令行的形式计算启动时间。

    logcat日志

    根据系统日志来统计启动耗时,在Android Studio中查找已用时间,必须在logcat视图中禁用过滤器(No Filters)。因为这个是系统的日志输出,而不是应用程序的。你也可以查看其它应用程序的启动耗时。

    过滤displayed输出的启动日志.

     

    但是这种方法只能统计Activity的从触发到完全显示的时间,但是没有包含网络访问、故意停留和用户操作的时间,所以也不能准确的反映启动时间。

    其他统计

    Testin云测的启动时间并不准确,大部分在1s以内,显然不可能。网易云笔记推荐的NimbleAPP已变成付费服务,且价格需要商谈,所以也不推荐。友盟上未找到关于APP启动时间的字段。

    自定义统计时间

    在APP的attachBaseContext()的最后加入

    val sp:SharedPreferences = getSharedPreferences("sp_hzgovernment", Context.MODE_PRIVATE)  
    sp.edit().putLong("application_attach_time", System.currentTimeMillis()).apply()  

    然后在MainActivity的onCreate()前边添加如下代码

    var appAttachTime = SPUtils.getLong("application_attach_time", 0);  
    var diffTime = System.currentTimeMillis() - appAttachTime;//从application到入口Acitity的时间  
    Log.i("Total Time", diffTime.toString() + "ms")  

    就可以统计出从App启动,到首页开始加载的时长

    针对目前APP的优化目标

    现在的启动时长

     

    第一次启动

    第二次启动

    小米MIX2S

    14.6s

    8.3s

    华为荣耀7X

    20.7s

    9.3s

    OPPO A37f

    14.2s

    9.8s

    第一次启动指首次安装后的打开应用,包括授权和引导页的操作时间

    第二次启动指打开过一次后的再次启动,不包括授权,广告页不点跳过

    误差:操作系统工作时长并未计算在内,因此实际启动比上面的时间长1到2秒

    启动时长分析

    以小米MIX2S为准

    第一次启动

    点击桌面图标

    空窗口

    闪屏页启动

    授予权限

    闪屏页停留

    引导页启动

    引导页操作

    跳转主页

    开始

    启动时长------》

    结束

     

    约2s

    1.1s

    4s

    2.2s

    0.3s

    2s

     

    第二次启动

    点击桌面图标

    空窗口

    闪屏页启动

    闪屏页停留

    广告页启动

    广告页停留

    跳转主页

    开始

    启动时长-------》

    结束

     

    约2s

    1.1s

    2.2s

    0.2s

    4s

     

    优化目标

    点击图标后有更快响应

    用户体验到的启动速度有明显提升(首次启动时间提高30%以上,第二次启动时间提高20%以上)

    参考引文

    1.《Android 性能优化(一) —— 启动优化提升60%》

    2.《android app的启动流程》

    3.《App startup time》

    4.《如何统计Android App启动时间》

    展开全文
  • 一、App启动分类 1.冷启动 Cold start 在启动应用前,系统还没有App的任何进程。比如设备开机后应用的第一次启动,系统杀掉应用进程 (如:系统内存吃紧引发的 kill 和 用户主动产生的 kill) 后 的再次启动等。那么...

    一、App启动分类

    1.冷启动 Cold start

    在启动应用前,系统还没有App的任何进程。比如设备开机后应用的第一次启动,系统杀掉应用进程 (如:系统内存吃紧引发的 kill 和 用户主动产生的 kill) 后 的再次启动等。那么自然这种方式下,应用的启动时间最长。

    2.热启动 Warm start
    当应用中的 Activities 被销毁,但在内存中常驻时,应用的启动方式就会变为暖启动。相比冷启动,暖启动过程减少了对象初始化、UI的布局和渲染。启动时间更短。但启动时,系统依然会展示一个空白背景,直到第一个 Activity 的内容呈现为止。

    3.温启动 Lukewarm start
    用户退出您的应用,但随后重新启动。该过程可能已继续运行,但应用程序必须通过调用onCreate()从头开始重新创建活动。系统从内存中驱逐您的应用程序,然后用户重新启动它。进程和Activity需要重新启动,但任务可以从保存的实例状态包传递到onCreate()中。

    启动速度优化主要是针对冷启动方式。下面看下冷启动的时候会做哪些工作。

    #二、冷启动
    应用发生冷启动时,系统有三件任务要做:

    • 加载启动App;
    • App启动之后立即展示出一个空白的Window;
    • 创建App的进程;

    创建App进程后,会马上执行以下任务:

    • 初始化应用中的对象 (比如 Application 中的工作);
    • 启动主线程 (UI 线程) ;
    • 创建第一个 Activity;
    • 加载内容视图 (Inflating) ;
    • 计算视图在屏幕上的位置排版 (Laying out);
    • 进行第一次绘制 (draw)。

    只有当应用完成第一次绘制,系统当前展示的空白背景才会消失,才会被 Activity 的内容视图替换掉。也就是这个时候,用户才能和我们的应用开始交互。下图展示了冷启动过程系统和应用的一个工作时间流:

    三、优化思路

    作为普通应用,App进程的创建等环节我们是无法主动控制的。开发人员唯一能做的就是**在Application 和 第一个 Activity 中,减少 onCreate() 方法的工作量,从而缩短冷启动的时间。**像应用中嵌入的一些第三方 SDK,都建议在 Application 中做一些初始化工作,开发人员不妨采取懒加载的形式移除这部分代码,而在真正需要用到第三方 SDK 时再进行初始化。

    Google也给出了启动加速的方向:

    1、利用提前展示出来的Window,快速展示出来一个界面,给用户快速反馈的体验;
    2、 避免在启动时做密集沉重的初始化(Heavy app initialization);
    3、 定位问题:避免I/O操作、反序列化、网络操作、布局嵌套等

    四、正确测量评估启动性能的方法

    1.display time

    从Android KitKat版本开始,Logcat中会输出从程序启动到某个Activity显示到画面上所花费的时间。这个方法比较适合测量程序的启动时间。

    2.reportFullyDrawn

    我们通常来说会使用异步懒加载的方式来提升程序画面的显示速度,这通常会导致的一个问题是,程序画面已经显示,可是内容却还在加载中。为了衡量这些异步加载资源所耗费的时间,我们可以在异步加载完毕之后调用activity.reportFullyDrawn()方法来告诉系统此时的状态,以便获取整个加载的耗时。

    3.Traceview

    告诉我们每一个方法执行了多长时间.这个工具可以通过 Android Device Monitor 或者从代码中启动。

    3.1 Android Device Monitor启动

    启动应用,点击 Start Method Tracing,应用启动后再次点击,会自动打开刚才操作所记录下的.trace文件,建议使用DDMS来查看,功能更加方便全面。

    3.2 代码启动

    ①在onCreate开始和结尾打上trace

        Debug.startMethodTracing("GithubApp");
    	...
    	Debug.stopMethodTracing();
    

    注意加读写权限

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    

    运行程序, 会在sdcard上生成一个"GithubApp.trace"的文件.

    ②通过adb pull将文件导出到本地

    adb pull /sdcard/GithubApp.trace ~/temp
    

    ③打开DDMS分析trace文件
    ④分析trace文件

    • 在下方的方法区点击"Real Time/Call", 按照方法每次调用耗时降序排.
    • 耗时超过500ms都是值得注意的.
    • 看左边的方法名, 可以看到耗时大户就是我们用的几大平台的初始化方法, 特别是Bugly, 还加载native的lib, 用ZipFile操作-等.
    • 点击每个方法, 可以看到其父方法(调用它的)和它的所有子方法(它调用的).
    • 点击方法时, 上方的该方法执行时间轴会闪动, 可以看该方法的执行线程及相对时长.

    4.Systrace

    在onCreate方法里面添加trace.beginSection()与trace.endSection()方法来声明需要跟踪的起止位置,系统会帮忙统计中间经历过的函数调用耗时,并输出报表。

    5.adb命令计算 App 的启动时间

    adb shell am start -W packageName/packageName.activity
    

    例如:

    adb shell am start -W com.media.painter/com.media.painter.PainterMainActivity
    Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.media.painter/.PainterMainActivity }
    Status: ok
    Activity: com.media.painter/.PainterMainActivity
    ThisTime: 355
    TotalTime: 355
    WaitTime: 365
    Complete
    

    (注意 Android 5.0 之前的手机是没有 WaitTime 这个值的)

    • WaitTime 就是总的耗时,包括前一个应用 Activity pause 的时间和新应用启动的时间;
    • ThisTime 表示一连串启动 Activity 的最后一个 Activity 的启动耗时;
    • TotalTime 表示新应用启动的耗时,包括新进程的启动和 Activity 的启动,但不包括前一个应用 Activity pause 的耗时。
    • 开发者一般只要关心 TotalTime 即可,这个时间才是自己应用真正启动的耗时。

    五、优化方案

    1.主题切换

    通过主题设置,不显示启动时的白屏背景。有以下几种方案:

    1.1 直接不显示白屏,直到程序初始化完毕直接显示第一个Activity

    <style name="LaunchStyle" parent="Theme.AppCompat.Light.DarkActionBar">
    		    ......
    		    <item name="android:windowIsTranslucent">true</item>
    		    <item name="android:windowNoTitle">true</item>
    </style>
    

    或者

        <style name="LaunchStyle" parent="Theme.AppCompat.Light.DarkActionBar">
    	    ......
    	    <item name="android:windowDisablePreview">true</item>
        </style>
    

    然后设置给第一个activity

    	<activity 
    	    android:name=".MainActivity"
    	    android:theme="@style/LaunchStyle">
    	    <intent-filter>
    	        <action android:name="android.intent.action.MAIN" />
    	        <category android:name="android.intent.category.LAUNCHER" />
    	    </intent-filter>
    	</activity>
    

    如果将主题设置到Application,那所有的Activity的主题都会改变

    然后在MainActivity中在加载布局之前,重新设置主题

    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
            setTheme(R.style.AppTheme);
    	    super.onCreate(savedInstanceState);
    	    
    	    setContentView(R.layout.activity_main);
    	}
    

    这样相当于把白屏变成透明的,隐藏起来了,但是会有一种点击图标后卡住了,过了好几秒才进入App的感觉。这种方案用户体验很差。

    1.2把白屏当成闪屏页用

    可以通过主题中的 windowBackground 属性,自定义应用启动时的窗口背景。窗口背景显示的内容,Google推荐两种方案,一种是显示Logo,一种利用了 placeholder ,与主界面的 UI 框架保持一致,给用户产生一种应用启动非常快的视觉感受。

    ①显示Logo使用方式:

    drawable/branded_launch_screens:

    	<?xml version="1.0" encoding="utf-8"?>
    	<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    	    android:opacity="opaque">
    	    <!--黑色背景颜色-->
    	    <item android:drawable="@android:color/black" />
    	    <!-- 产品logo-->
    	    <item>
    	        <bitmap
    	            android:gravity="center"
    	            android:src="@mipmap/empty_image01" />
    	    </item>
    	    <!-- 右上角的图标元素 -->
    	    <item>
    	        <bitmap
    	            android:gravity="top|right"
    	            android:src="@mipmap/github" />
    	    </item>
    	    <!--最下面的文字-->
    	    <item android:bottom="50dp">
    	        <bitmap
    	            android:gravity="bottom"
    	            android:src="@mipmap/ic_launcher" />
    	    </item>
    	</layer-list>
    

    android:opacity=”opaque”参数是为了防止在启动的时候出现背景的闪烁。

    定义style:

        <style name="AppTheme.Launcher">
           <item name="android:windowBackground">@drawable/branded_launch_screens</item>
        </style>
    

    或者直接使用一张图片

    	<style name="AppTheme.Launcher">
    	    <item name="android:windowFullscreen">true</item>
    	    <item name="android:windowBackground">@mipmap/app_welcome</item>
    	</style>
    

    然后将这个主题设置给启动的 Activity。

    ②使用placeholder:

    模拟了一个高度为25dp的状态栏和一个高度为56dp的标题栏。
    drawable/placeholder_ui

    	<?xml version="1.0" encoding="utf-8"?>
    	<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    	    android:opacity="opaque">
    	    <!--状态栏颜色-->
    	    <item android:drawable="@color/colorPrimaryDark" />
    	    <!--假装这里是个toolbar-->
    	    <item
    	        android:drawable="@color/colorPrimary"
    	        android:top="25dp" />
    	    <!--状态栏25+toolbar56=距离top81-->
    	    <item
    	        android:drawable="@android:color/white"
    	        android:top="81dp" />
    	</layer-list>
    

    定义style:

    	<style name="AppTheme.Launcher">
    	    <item name="android:windowBackground">@drawable/placeholder_ui</item>
    	</style>
    

    然后将这个主题设置给启动的 Activity。

    ③还可以适度结合 Activity 内容视图使用动画过渡效果。

    2.避免Application的onCreate进行太多的工作

    在Application初始化的地方做太多繁重的事情是可能导致严重启动性能问题的元凶之一。Application里面的初始化操作不结束,其他任意的程序操作都无法进行。Application的onCreate中会做大量第三方组件的初始化工作,其实很多组件是需要做区别对待的,有些可以做延迟加载,有些可以放到其他的地方做初始化操作,特别需要留意包含Disk IO操作,网络访问等严重耗时的任务,他们会严重阻塞程序的启动。

    注意点:

    • 项目是多进程架构,只在主进程执行Application的onCreate();
    • 流程梳理,延后执行;
    • 异步加载、延时加载、懒加载

    示例如下,Application以及首屏Activity中我们主要做了:

    如何判断第三方的库是不是能放在子线程里面:

    需要初始化的第三方一般分为两种, 一种是第三方平台的SDK(推送, 分享, 反馈, 统计等) 这个可以通过看其SDK文档, 结合业务需求考虑. 例如分享, 反馈一般不是必须要应用一开启就能用的, 这类业务一般层级比较深, 有足够的理由让它们在后台异步初始化. 另外一种第三方是第三方的库, 一般来说, 建议阅读其源码, 了解其实现原理, 再决定是否放在后台初始化.

    项目修改:

    将友盟、Bugly、听云、GrowingIO、BlockCanary等组件放在WorkThread中初始化;

    延迟地图定位、ImageLoader、自有统计等组件的初始化:地图及自有统计延迟4秒,此时应用已经打开;而ImageLoader因为调用关系不能异步以及过久延迟,初始化从Application延迟到SplashActivity;而EventBus因为再Activity中使用所以必须在Application中初始化。

    3.避免首个Activity的onCreate进行太多的工作

    使用延迟加载。确保在Activity的页面显示出来之后再进行加载数据,避免过早或过晚的加载导致页面空白时间过长。可采用以下 代码实现延迟加载。在Activity的onCreate方法中:

    getWindow().getDecorView().post(new Runnable() {
      @Override
      public void run() {
        myHandler.post(mLoadingRunnable);
      }
    });
    

    4.MultiDex初次启动优化

    4.1问题

    随着代码数量的膨胀,工程本身的代码加上引用的第三方库的代码中方法数量会超过65536的限制。是由于DEX文件格式限制,一个DEX文件中method个数采用使用原生类型short来索引文件中的方法,也就是4个字节共计最多表达65536个method,field/class的个数也均有此限制。 Google为构建超过65K方法数的应用提供官方支持的方案:MultiDex。

    但是在Dalvik下MultiDex有个问题:5.0以下某些低端机会出现ANR或者长时间卡顿不进入引导页,而罪魁祸首是MultiDex.install(Context context)的dexopt过程耗时过长。因此需要在初次启动时做特别处理。

    而5.0以上会使用ART,在ART下MultiDex是不存在这个问题的,这主要是因为ART下采用Ahead-of-time (AOT) compilation技术,系统在APK的安装过程中会使用自带的dex2oat工具对APK中可用的DEX文件进行编译并生成一个可在本地机器上运行的文件,这样能提高应用的启动速度,只是在安装过程中进行了处理这样会影响应用的安装速度。

    4.2解决思路

    1、在Application.attachBaseContext(Context base)中,判断是否初次启动,以及系统版本是否小于5.0,如果是,跳到2;否则,直接执行MultiDex.install(Context context)。

    2、开启一个新进程,在这个进程中执行MultiDex.install(Context context)。执行完毕,唤醒主进程,自身结束。主进程在开启新进程后,自身是挂起的,直到被唤醒。

    3、唤醒的主进程继续执行初始化操作。

    最后

    如果你看到了这里,觉得文章写得不错就点个赞呗?转发分享关注一下我,以后还会更新技术干货,谢谢您的支持!如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。

    有一句老话说的好:
    “比你优秀的对手在学习,你的仇人在磨刀,你的闺蜜在减肥,隔壁老王在练腰,我们必须不断学习,否则我们将被学习者超越。”
    当然一个人学习是枯燥的,还需要一个良好的学习氛围,因此我组建了一个学习交流探讨的社群,欢迎大家一起来交流探讨共同进步。还有一些收集整理的资料,感兴趣的可以来一起学习,共同进步!

    针对Android开发的同行,这边给大家整理了一些资料,其中分享内容包括但不限于
    【高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术】
    希望能帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也是可以分享给身边好友一起学习的!

    转发+点赞,加入Android开发交流群(820198451)获取小编为大家收录的进阶资料和面试题库


    在这里插入图片描述

    转发+点赞,加入Android开发交流群(820198451)获取小编为大家收录的进阶资料和面试题库

    Android架构师之路很漫长,一起共勉吧!

    展开全文
  • Android性能调优:App启动速度优化

    千次阅读 2019-07-11 15:51:36
    一、App启动分类 1.冷启动 Cold start 在启动应用前,系统还没有App的任何进程。比如设备开机后应用的第一次启动,系统杀掉应用进程 (如:系统内存吃紧引发的 kill 和 用户主动产生的 kill) 后 的再次启动等。那么...
  • app启动的白屏黑屏 开发中会在Activity的onCreate()方法中调用setContentView(View)设置该Activity的布局,那么问题就来了,既然我们设置了布局,为什么启动的时候还会白屏或者黑屏而不是显示set的布局呢?...
  • 本文参考了目前大部分 Android 应用启动优化的方案,将大家的方案做一个汇总,如果你有这方面的需求,只需要对照这篇文章,看看其他人的方案,查漏补缺。很多方案是要根据具体的业务去做优化的,所以这里也没有对每...
  • 应用的启动速度缓慢这是很多开发者都遇到的一个问题,比如启动缓慢导致的黑屏,白屏问题,大部分的答案都是做一个透明的主题,或者是做一个Splash界面,但是这并没有从根本上解决这个问题。那么如何从根本上解决这个...
  • APP启动如果得到很好的优化,增强用户体验增加用户流量;如果app启动时间过长影响用户体验,从而会造成流失用户。所以做启动优化是有必须的。 二. 应用启动类型 1. 冷启动 概念:当应用在设备开机或者系统主动 ...
  • Android性能优化系列之App启动优化

    万次阅读 多人点赞 2017-02-22 00:23:29
    Android性能优化系列之布局优化Android性能优化系列之内存优化Android性能优化系列之apk瘦身应用的启动速度缓慢是我们在开发过程中经常会遇到的问题,比如启动缓慢导致的黑屏,白屏问题,本篇博客就将介绍App启动...
  • Android App启动速度优化 主要分两步: 1. 找出启动过程中,在主线程上耗时的操作函数 2. 修改它,让它延时操作、或者运行在子线程 我觉得这里面最最主要的工作是第一点是,找出耗时的操作。 如何找到耗时的...
  • 通常来说,在安卓中应用的启动方式分为两种:冷启动和热启动。 1、冷启动:当启动应用时。后台没有该应用的进程,这时系统会又一次创建一个新的进程分配给该应用,这个启动方式就是冷启动。 2、热启动:当启动...
  • Android启动速度优化

    万次阅读 2018-04-23 16:20:54
    最近做了一些Android App启动速度优化,有一些心得,整理整理 影响启动速度的原因 高耗时任务 数据库初始化、某些第三方框架初始化、大文件读取、MultiDex加载等,导致CPU阻塞 复杂的View层级 使用的...
  • 你有没有被App启动速度过慢这个问题所困扰过呢?Android应用程序的性能优化是个很深的话题,而性能优化的第一步就是如何让我们的App启动速度变得更快。在启动问题上,A...
  • 第一种方式:直接在Logcat中查看,Android应用启动的时候会打印出app启动时间,不过要在过滤框中输入 Displayed 来过滤查看: 第二种方式: 使用 adb 命令,这里不详解 adb,有疑问的可以自行谷歌 二、...
  • 通常来说,在安卓中应用的启动方式分为两种:冷启动和热启动。 1、冷启动:当启动应用时。后台没有该应用的进程,这时系统会又一次创建一个新的进程分配给该应用,这个启动方式就是冷启动。 2、热启动:当启动应用...
  • 通常来说,在安卓中应用的启动方式分为两种:冷启动和热启动。 1、冷启动:当启动应用时。后台没有该应用的进程,这时系统会又一次创建一个新的进程分配给该应用,这个启动方式就是冷启动。 2、热启动:当启动...
  • 安卓app启动速度优化

    2018-09-08 21:41:25
    随着app的迭代功能也会越来越多,一些功能难免要启动时初始化,这样会使应用的启动速度变慢,提升启动速度迫在眉睫,如果不是非必须应用,很有可能分分钟被卸载,优化启动速度这里需要用到一个theme属性 ​&lt...
  • 1、冷启动:冷启动由于系统会又一次创建一个新的进程分配给它。所以会先创建和初始化Application类,再创建和初始化MainActivity类(包含一系列的測量、布局、绘制),最后显示在界面上。 2、热启动:热启动由于会从...
  • 当大家要改善APP启动速度优化的时候,首先要知道App的启动时间,那么改如何统计时间呢,下面我们一起来看看。
  • 一、欲善其事, 先利其器 1.1 Traceview介绍 ...二、App启动流程分析 三、App启动方式 3.1 冷启动 3.2 热启动 3.3 温启动 四、App快速启动敌人 五、结语 作者:anly_jun 链接:https://www.jian...
  •   Android app 启动速度优化,首先谈谈为什么会走到优化这一步,如果一开始创建 app 项目的时候就把这个启动速度考虑进去,那么肯定就不需要重新再来优化一遍了。这是因为在移动互联网时代,大家都追求快,什么...
  • 引言 前篇文章花了相当大的篇幅从理论和源码角度总结了APP启动背后的故事和原理...Android进阶——性能优化APP启动时黑白屏的根源解析及对应的优化措施小结(一) Android进阶——性能优化APP启动过程相关源码...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,160
精华内容 9,264
关键字:

安卓app启动速度优化