APP 启动优化

本文深入探讨App启动过程中的冷启动、热启动与暖启动概念,分析启动时出现白屏的原因,并提供两种有效解决方案:一是修改AppTheme主题背景,二是自定义启动Activity主题,通过展示定制的启动画面提升用户体验。

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 标签可以进行布局的懒加载

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值