Android优化提升应用启动速度及Splash页面的设计

目录
  • 1.启动分为两种方式
  • 2.如何测量一个应用的启动时间
  • 3.应用启动的流程
  • 4.减少应用的启动时间的耗时
  • 5.如何设计延迟加载DelayLoad

1.启动分为两种方式

  • 1) 冷启动:当直接从桌面上直接启动,同时后台没有该进程的缓存,这个时候系统就需要重新创建一个新的进程并且分配各种资源。
  • 2) 热启动:app后台有该进程的缓存,这时候启动的进程就属于热启动。
  • 热启动不需要重新分配进程,也不会Application了,直接走的就是app的入口Activity,这样速度就很快

2.如何测量一个应用的启动时间

使用命令行来启动app,同时进行时间测量。单位:毫秒

 adb shell am start - W [PackageName] /[PackageName.MainActivity]

例: adb shell am start -W com.haocai.app/.activity.GuideActivity

热启动耗时:

打印的结果为:

  • ThisTime activity启动耗时
  • TotalTime 应用自身启动耗时=ThisTime+应用application等资源启动时间
  • WaitTime 系统启动应用耗时=TotalTime+系统资源启动时间

3.应用启动的流程

Application从构造方法开始 ---> attachBaseContext() ---> onCreate()
Activity
构造方法 ---> onCreate() ---> 设置显示界面布局,设置主题、背景等等属性 ---> onStart()
---> onResume() ---> 显示里面的View(测量、布局、绘制,显示到界面上)

从构造方法我们知道,启动耗时的主要花费在各个启动流程中

4.减少应用的启动时间的耗时

根据应用的启动流程,我们从而得到以下减少应用启动耗时操作的建议:

  • 不要在Application的构造方法、attachBaseContext()onCreate()里面进行初始化耗时操作。
  • MainActivity,由于用户只关心最后显示的这一帧,对我们的布局的层次要求减 自定义控件的测量、布局、绘制的时间。 同时 不要在onCreateonStartonResume当中的做耗时操作。
  • 对于SharedPreference的初始化

因为它初始化的时候是需要将数据全部读取出来放到内存当中。

  • 优化1:可以尽可能减少sp文件数量(IO需要时间)
  • 优化2:像这样的初始化最好放到线程里面
  • 优化3:大量的数据缓存到数据库中

app启动的耗时主要在:Application初始化 + MainActivity的界面加载绘制时间。

由于MainActvity的业务和布局复杂度非常高,甚至该界面必须要有一些初始化的数据才能显示。
那么这个时候MainActivity就可能半天都出不来,这就给用户感觉App太卡了。

常规方法:

1.我们要做的就是给用户赶紧利落的体验。点击app就立马弹出我们的界面。
于是乎想到使用SplashActivity--非常简单的一个欢迎页面上面都不干就只显示一个图片。
2.但是SplashActivity启动之后,还是需要跳到MainActivityMainActivity还是需要从头开始加载布局和数据。
想到SplashActivity里面可以去做一些MainActivity的数据的预加载。然后需要通过意图传到MainActivity

更好的优化:

耗时的问题:Application+Activity的启动及资源加载时间;预加载的数据花的时间。

如果我们能让这两个时间重叠在一个时间段内并发地做这两个事情就省时间了。

比如:SplashActivityMainActivity合为一个。

一进来还是显示MainActivitySplashActivity可以变成一个SplashFragment,然后放一个FrameLayout作为根布局直接显示SplashFragment界面。
SplashFragment里面非常之简单,就是现实一个图片,启动非常快。

SplashFragment显示完毕后再将它remove。同时在splash的2S的友好时间内进行网络数据缓存。
这个时候我们才看到MainActivity,就不必再去等待网络数据返回了。

新问题SplashViewContentView加载放到一起来做了 ,这可能会影响应用的启动时间?

解决:可以使用ViewStub延迟加载MainActivity当中的View来达到减轻这个影响。
viewStub的设计就是为了防止MainActivity的启动加载资源太耗时了。延迟进行加载,不影响启动,用户友好。
但是viewStub加载也需要时间。等到主界面出来以后。
viewStub.inflate(xxxx);

5.如何设计延迟加载DelayLoad

第一时间想到的就是在onCreate里面调用Handler.postDelayed()方法;
问题一:这个延时时间如何控制
不同的机器启动速度不一样,这个时间如何控制?
假设,先需要splash做一个2s动画,然后在MainActivity中主界面加载完成之后,关闭splash页面

如果这样写:

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mProgressBar.setVisibility(View.GONE);
                iv.setVisibility(View.VISIBLE);
            }
        }, 2500);

是无法在准确监听页面加载完的

问题:什么时候应用已经启动并加载完成,界面已经显示出来了。
采用onResume执行完了之后才显示完毕?不行。

建议采用getDecorView() 获取上级view 然后添加视图

综合上诉方案,以下是关键代码:

public class MainActivity extends AppCompatActivity {

    private Handler mHandler = new Handler();
    private SplashFragment splashFragment;
    private ViewStub viewStub;

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

        splashFragment = new SplashFragment();
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.frame, splashFragment);
        transaction.commit();

        /**
         *这么写不好判断视图有没有加载完
         */
        //      mHandler.postDelayed(new Runnable() {
//          @Override
//          public void run() {
//              mProgressBar.setVisibility(View.GONE);
//              iv.setVisibility(View.VISIBLE);
//          }
//      }, 2500);

        viewStub = (ViewStub) findViewById(R.id.content_viewstub);

        //1.判断当窗体加载完毕的时候,立马再加载真正的布局进来
        getWindow().getDecorView().post(new Runnable() {

            @Override
            public void run() {
                // 开启延迟加载
                mHandler.post(new Runnable() {

                    @Override
                    public void run() {
                        //将viewstub加载进来
                        viewStub.inflate();
                    }
                });
            }
        });

        //2.判断当窗体加载完毕的时候执行,延迟一段时间做动画。
        getWindow().getDecorView().post(new Runnable() {
            @Override
            public void run() {
                // 开启延迟加载,也可以不用延迟可以立马执行(我这里延迟是为了实现fragment里面的动画效果的耗时)
                mHandler.postDelayed(new DelayRunnable(MainActivity.this, splashFragment), 2000);
            }
        });

    //3.同时进行异步加载数据
        //......
    }

    static class DelayRunnable implements Runnable {

        private WeakReference<Context> contextWeakReference;
        private WeakReference<SplashFragment> splashFragmentWeakReference;

        public DelayRunnable(Context context, SplashFragment f) {
            contextWeakReference = new WeakReference<Context>(context);
            splashFragmentWeakReference = new WeakReference<SplashFragment>(f);
        }

        @Override
        public void run() {
            //移除Fragment
            if (contextWeakReference != null) {
                SplashFragment splashFragment = splashFragmentWeakReference.get();
                if (splashFragment == null) {
                    return;
                }
                FragmentActivity activity = (FragmentActivity) contextWeakReference.get();
                FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
                transaction.remove(splashFragment);
                transaction.commit();
            }

        }
    }
}

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   >

    <ViewStub
        android:id="@+id/content_viewstub"
        android:layout="@layout/activity_main_viewstub"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <FrameLayout
        android:id="@+id/frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </FrameLayout>

</RelativeLayout>

ps:测试数据是在老款三星手机下所得耗时数据。
不过相较于SplashActivity+MainActivity启动速度优化还是挺明显的。大家可以在自己手机上试试。

到此这篇关于Android提升应用启动速度及Splash页面的设计的文章就介绍到这了,更多相关Android性能优化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android实战APP启动速度优化

    APP启动速度非常重要,APP启动速度慢,可能会造成用户体验不良好,尤其是在最近用Android studio之后,如果长时间不打开app,启动速度就会特别的慢,下面我们一起探讨一下影响app启动速度的原因,以及解决方案. 检测启动时间 首先我们要知道app的启动时间,然后你也可以凭着感觉来,这里我教大家一个装逼的方法: adb shell am start -W [packageName]/[.MainActivity] 用adb命令可以检测启动时间,示例如下: ./adb shell am

  • Android应用启动速度优化

    开发Android应用中,随着功能越来越多,启动速度越来越慢.有没有办法让自己应用启动速度快一点呢? 方法是人想出来的.先说说我的实现方法: 1 将onCreate 中初始化的内容,移动到线程中做初始化,加载等 2 初始化完成之后,通过Handler发送消息, 3 Hander 中收到消息后,再初始化完整界面. public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedIn

  • Android性能优化方案详情

    目录 1.指标 2.包大小优化 3.响应时间优化 4.内存优化 5.CPU优化 6.耗电量优化 前言: 上一个季度在百度工作挺忙碌,在最后期限完成了OKR目标,因此有一段时间没有写文章.今天趁有机会想分享下在大型Android项目工程内的一些性能优化方式. 1.指标 量化性能的指标有很多,但最重要的就是以下5种: 包大小 响应时间 内存 CPU 耗电量 优化性能就是可以从以上5点入手. 2.包大小优化 顾名思义就是减少apk包体积大小,apk大小主要取决于res下的资源文件..class文件,

  • Android 进阶实现性能优化之OOM与Leakcanary详解原理

    目录 Android内存泄漏常见场景以及解决方案 资源性对象未关闭 注册对象未注销 类的静态变量持有大数据 单例造成的内存泄漏 非静态内部类的静态实例 Handler临时性内存泄漏 容器中的对象没清理造成的内存泄漏 WebView 使用ListView时造成的内存泄漏 Leakcanary leakcanary 导入 leakcanary 是如何安装的 leakcanary 如何监听Activity.Fragment销毁 RefWatcher 核心原理 流程图 本文主要探讨以下几个问题: And

  • Android 性能优化系列之bitmap图片优化

    背景 Android开发中,加载图片过多.过大很容易引起OutOfMemoryError异常,即我们常见的内存溢出.因为Android对单个应用施加内存限制,默认分配的内存只有几M(具体视不同系统而定).而载入的图片如果是JPG之类的压缩格式(JPG支持最高级别的压缩,不过该压缩是有损的),在内存中展开会占用大量的内存空间,也就容易形成内存溢出.那么高效的加载Bitmap是很重要的事情.Bitmap在Android中指的是一张图片,图片的格式有.jpg .jpg .webp 等常见的格式. 如何

  • Android性能优化及性能优化工具

    目录 1.Allaction Tracking (1)追踪 (2)分类我们的内存分配 (3)查看统计图 2.LeakCanary (1)配置 (2)制造一个单例内存泄漏的点 (3)LeakCanary 发出内存泄漏通知 (4)LeakCanary 分析 3.Lint分析工具  性能优化的帮助工具: MAT, Memory Monitor(属于AndroidMonitor中一个模块), HeapTool(查看堆信息), Allaction Tracking, LeakCanary Lint工具 1

  • Android 分析实现性能优化之启动速度优化

    目录 启动方式 冷启动(启动优化目标) 热启动 温启动 启动流程中可优化的环节 检测工具 启动时间检测 Logcat Displayed adb 命令统计 CPU profile API level >= 26 API level < 26 StrictMode 严苛模式 优化点 黑白屏问题 本文主要探讨以下几个问题: 启动方式 启动流程中可优化的环节 检测工具 优化点 黑白屏问题 启动方式 应用有三种启动状态,每种状态都会影响应用向用户显示所需的时间:冷启动.温启动与热启动 冷启动(启动优化

  • Android优化提升应用启动速度及Splash页面的设计

    目录 1.启动分为两种方式 2.如何测量一个应用的启动时间 3.应用启动的流程 4.减少应用的启动时间的耗时 5.如何设计延迟加载DelayLoad 1.启动分为两种方式 1) 冷启动:当直接从桌面上直接启动,同时后台没有该进程的缓存,这个时候系统就需要重新创建一个新的进程并且分配各种资源. 2) 热启动:该app后台有该进程的缓存,这时候启动的进程就属于热启动. 热启动不需要重新分配进程,也不会Application了,直接走的就是app的入口Activity,这样速度就很快 2.如何测量一个

  • 详解Android中App的启动界面Splash的编写方法

    一.Splash界面的作用 用来展现产品的Logo 应用程序初始化的操作 检查应用程序的版本 检查当前应用程序是否合法注册 二.界面的xml定义 写一个布局背景设置为产品的logo图片,再添加一个textview显示版本号. <TextView android:id="@+id/tv_splash_version" android:layout_width="wrap_content" android:layout_height="wrap_cont

  • 分享五个PHP7性能优化提升技巧

    PHP7已经发布了, 作为PHP10年来最大的版本升级, 最大的性能升级, PHP7在多放的测试中都表现出很明显的性能提升, 然而, 为了让它能发挥出最大的性能, 我还是有几件事想提醒下. 1. Opcache 记得启用Zend Opcache, 因为PHP7即使不启用Opcache速度也比PHP-5.6启用了Opcache快, 所以之前测试时期就发生了有人一直没有启用Opcache的事情. 启用Opcache非常简单, 在php.ini配置文件中加入: zend_extension=opcac

  • Android 个人理财工具四:添加账单页面 下

    本文考虑把账单界面整理下,实现如下图中的功能.做之前感觉应该不难,但实际做时发现排列界面布局甚至比编写程序代码还要复杂.网上搜索发现,关于这种布局的资料能用的很少,Google Demo中用的最多的就是Listview了,但本实例的界面似乎要复杂一些. spinner和cursor如何配合使用成了完成此实例过程中的难点,本来应该很简单,但却把我郁闷坏了. 先给大家贴上最终的效果图片: 界面的xml: XML/HTML代码 <?xml version="1.0" encoding=

  • Android中使用TabHost 与 Fragment 制作页面切换效果

    三个标签页置于顶端 效果图: 在文件BoardTabHost.java中定义页面切换的效果:切换页面时,当前页面滑出,目标页面滑入.这是2个不同的动画设定动画时要区分对待 import android.content.Context; import android.util.AttributeSet; import android.view.animation.Animation; import android.view.animation.TranslateAnimation; import

  • Android 优化Handler防止内存泄露

    Android 优化Handler防止内存泄露 Demo描述: Handler可能导致的内存泄露及其优化 1 关于常见的Handler的用法但是可能导致内存泄露 2 优化方式请参考BetterHandler和BetterRunnable的实现 package cc.cc; import java.lang.ref.WeakReference; import android.os.Bundle; import android.os.Handler; import android.os.Messag

  • Android开发之ListView的head消失页面导航栏的渐变出现和隐藏

    1.Fragment页面xml布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"

  • Android开发实现自定义新闻加载页面功能实例

    本文实例讲述了Android开发实现自定义新闻加载页面功能.分享给大家供大家参考,具体如下: 一.概述: 1.效果演示: 2.说明:在新闻页面刚加载的时候,一般会出现五种状态 未知状态(STATE_UNKNOW).空状态(STATE_EMPTY).加载中(STATE_LOADING).错误(STATE_ERROT).成功(STATE_SUCCESS) 因为每个Detail页面都会出现,所以我们可以把他们封装成一个LoadPage的自定义view,可以复用 二.实现: 1.首先的定义三个布局,为什

  • Android 个人理财工具三:添加账单页面 上

    ColaBox 登记收支记录终于进入了复杂阶段了.这个界面我也是查找了很多资料以及打开android的源代码看了后才完成了,现在想来Google的开源真是明智的啊. 从前面的登录页面跳转进入添加账单页面.这个页面主要是用来登记收支记录的.说白了就是往数据库录入明细. 表结构如下: db.execSQL("CREATE TABLE bills ("                  + "_ID INTEGER PRIMARY KEY," //id          

  • Android 7.0系统webview 显示https页面空白处理方法

    最近开发的时候,偶尔遇到在线上稳定运行的webview内嵌的h5页面加载不出来,一直定位不到具体原因(因为我们自己做的兼容性测试上不重现),看系统日志也没有发现什么问题,后来咨询了用户手机的型号,发现是7.0或者6.0以上的个别机型会出现. 后来借到了一台业务的手机,型号是:三星 S6 EDGE,SM-G9205,在大多数机型上运行正常的页面,在这个机器上如下图: 这个页面在近期的变更是从http切换到https,由于之前的页面是http,我们在切换的时候,除了url之外,并未对webview的

随机推荐