APP 启动优化

Posted xyTianZhao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了APP 启动优化相关的知识,希望对你有一定的参考价值。

APP 启动优化

我们 android 开发永远也摆脱不了性能优化的需求,做的 App 就是给用户用的,随着功能的增加,App启动功能的丰富。

点击启动图标时,我们的 App 启动会出现一个白屏页面。这个非常影响交互体验。这节我们就来看看怎么优化这里

启动方式

首先,我们来看看 App 的启动方式都有哪些

冷启动

程序从头开始,系统灭有为该程序创建进程。
一般有两种场景:
1. 程序安装后的第一次启动
2. 应用程序被系统完全终止后再次打开

热启动

此时程序仍然驻留在内存之中,只是被系统从后台带入到前台,因此程序可以避免重复对象的初始化,加载布局和渲染。

需要注意的是,如果程序的某些内存被系统清除后,比如调用了 onTrimMemory方法,则需要重新创建这些对象以相应热启动事件。

暖启动

它包含热启动和冷启动一系列的操作子集,比热启动稍微消耗多一点。

与热启动的区别:暖启动必须调用 onCreate方法开始重新创建活动,也可以从传递给 onCreate方法中保存的实例状态中获取某些对象的恢复。

黑白屏原因

上面我们说的 App 启动时会有个白屏,那是因为当系统加载并启动 App 时,需要耗费相应的时间,即使时间不到 1s,用户也会感觉到当点击 App 图标时会有“延迟”现象。
为了解决这问题, Google 的做法是在 App 创建的过程中,先展示一个空白页面,让用户体会到点击图标之后立马就有响应;而这个空白页面的颜色则是根据我们在 Manifest 文件中配置的主题背景颜色来决定的;现在一般默认是白色;

解决方案

这是 Google 官方为了用户体验做的一些操作。但是在我们看来还是有一定的体验缺陷,没办法,产品提的,就算头发掉光,我们也得解决呀。

对此。业界有这么两种解决方式,不过大多数都倾向于第二种

方案1

修改系统的 AppTheme 主题。

在应用默认的 Manifest 文件中,设置系统“取消预览(空白窗体)”为 true。或者设置空白窗体为透明。

这两种方式殊途同归,将 Theme 背景改为透明,这样用户在视觉上就看不到空白页了。

方案2

替换空白页,从交互和技术上同步入手解决这个问题

1、自定义集成 AppTheme 主题,设置相应的样式。
2、将启动 Activity 主题设置为自定义主题
3、在启动的 Activity 中调用 setTheme 方法,将主题重新设置为原来的系统主题(在 super.onCreate 方法之前调用)。

具体实现

这里我们就第二种方案实现以下,代码不是很多,这里就直接贴出来了。

<!-- 根据交互设计的背景页,App 启动时首先展示 -->
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/launchBackground"/>
    <item android:top="150dp">
        <bitmap android:src="@drawable/ic_launcher" android:gravity="top"/>
    </item>
</layer-list>
<!-- 自定义 style 主题 -->
<style name="AppTheme.LaunchTheme">
    <item name="android:windowBackground">@drawable/launch_bg</item>
    <item name="android:windowFullscreen">true</item>
    <item name="windowNoTitle">true</item>
</style>
<!-- Manifest 相关代码 -->
<application
    android:theme="@style/AppTheme.LaunchTheme"
    <activity android:name=".ui.SplashActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".MainActivity"/>
</application>
package com.wuba.demo.ui;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import com.wuba.demo.MainActivity;
import com.wuba.demo.R;


/**
 * Author silence.
 * Time:2020-03-02.
 * Desc:App 启动欢迎页(引导页)
 */
public class SplashActivity extends Activity 

    private static final String TAG = "SplashActivity";
    private CountDownTimer countDownTimer;
    private TextView jumpTime;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.acticity_splash);
        jumpTime = findViewById(R.id.jump_time);

        countDownTimer = new CountDownTimer(3000, 1000) 
            @Override
            public void onTick(long millisUntilFinished) 
                Log.d(TAG, "millisUntilFinished:" + millisUntilFinished);
                String lastTime = millisUntilFinished / 1000+1 + "s";
                jumpTime.setText(lastTime);
            

            @Override
            public void onFinish() 
                jump2Main();
            
        ;
        jumpTime.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                jump2Main();
            
        );
    

    private void jump2Main() 
        startActivity(new Intent(this, MainActivity.class));
        countDownTimer.cancel();
        finish();
    

    @Override
    protected void onResume() 
        super.onResume();
        countDownTimer.start();
    



<!-- 引导页布局文件 -->
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/jump_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="3s"
        android:layout_gravity="right"
        android:layout_margin="25dp"
        android:textColor="#FFF"
        android:textSize="40sp"/>

    <LinearLayout
        android:id="@+id/go"
        android:layout_width="wrap_content"
        android:layout_marginBottom="100dp"
        android:layout_gravity="bottom|center"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:contentDescription="@string/app_name"
            android:src="@drawable/ic_launcher"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="30sp"
            android:layout_marginLeft="15dp"
            android:textColor="#FFF"
            android:text="APP 启动优化"/>

    </LinearLayout>

</FrameLayout>

效果预览

拓展

这里我们从设计和技术的角度解决了 App 启动时的黑白屏问题。但是在我们实际开发中,经常会产品或者测试说这玩意怎么用起来这么卡。这个就只能从技术角度去分析解决了。

代码优化

在 App 启动的时候,我们经常在自定义的 Application 中初始化相关东西。比如依赖的 SDk ,随着业务越来越多,这块的逻辑也越来越复杂。这就意味着我们 Application 的 onCreate 方法执行时间将会越来越长,从而导致我们界面展示越来越延迟。

这里我们可以将一些功能放在子线程中初去初始化,这样就可以节省我们主线程的时间了,从而提高应用的展示时间。

UI 优化解决方案

而界面的卡顿主要是 UI 过度绘制导致的,具体解决方法可以从以下几个方面入手

1、布局中的背景是否必要,没必要可以移除掉
2、是否可以删除多余的布局,减少 View 的层级,尽量使布局扁平化
3、自定义 View 是否进行了相应的裁剪
4、使用 merge 标签可以排除掉一层 ViewGroup 标签
5、使用 ViewStub 标签可以进行布局的懒加载

以上是关于APP 启动优化的主要内容,如果未能解决你的问题,请参考以下文章

Android Bug分析系列:第三方平台安装app启动后,home键回到桌面后点击app启动时会再次启动入口类bug的原因剖析

转载Android Bug分析系列:第三方平台安装app启动后,home键回到桌面后点击app启动时会再次启动入口类bug的原因剖析

在Android系统上启动知乎app时会唤醒微信是啥原因?

第三节 比热容

iOS优化篇之App启动时间优化

APP 启动优化