Android优化之启动优化和黑白屏优化

2023-11-12


一、启动流程

1.开机启动流程

开机—>BootLoader(引导芯片)—>Linux(init,rc)—>init进程(id=1)—> zygote进程—>JVM,SystemServer等—>ActivityManagerService,SystemServerManager,Binder(线程池)—>launcher(app)

2.app启动流程

  • ActivityThread:main()函数,相当于一个Handler,主线程,UI线程
  • ApplicationThread:与AMS沟通桥梁
  • mInstrumentation:通过这个api启动app,用来跟踪Activity和Application生命周期的类
  • AMS:数据管理者

ActivityThread通过ApplicationThread去AMS中获取Application的一些信息,在mInstrumentation中通过反射来创建app,调用app.onCreate()启动app

app启动流程


二、启动分类

  • 冷启动

    • 加载并启动app

    • 启动后立即为该app显示一个空白窗口(白屏)

    • 创建App进程(创建应用程序对象)

    • 启动主线程,创建主Activity

    • 加载布局,绘制(替换白屏)

  • 热启动

    • 应用中所有Activity都还驻留在内存中,则无需重复对象初始化,将Activity带到前台即可
  • 温启动


三、黑白屏优化

黑白屏优化主要体现在视觉上的优化,通常我们会加一个启动页来填充我们启动的时间

1.写一个xml文件(activity_welcome)

主要有一个启动的background和一个右上角的跳过按钮

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/bg_welcome">

    <TextView
        android:id="@+id/skip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="25dp"
        android:layout_marginEnd="10dp"
        android:background="@drawable/bg_skip_tw"
        android:clickable="true"
        android:focusable="true"
        android:gravity="center"
        android:paddingLeft="12dp"
        android:paddingTop="7dp"
        android:paddingRight="12dp"
        android:paddingBottom="7dp"
        android:text="@string/ship_3s"
        android:textColor="@color/blue"
        android:textSize="14sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

2.welcomeActivity类

class WelcomeActivity : BaseActivity() {

    private val GO_HOME = 0 //去主页

    private val GO_LOGIN = 1 //去登录页


    var thread: timeThread? = null

//    val MSG = 1
    val handler = @SuppressLint("HandlerLeak")
    object : Handler() {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                GO_LOGIN -> {
                    skip.setText("跳过 " + msg.arg1)
                    if (msg.arg1 <= 0) {
                        val intent = Intent(this@WelcomeActivity, LoginWechatActivity::class.java)
                        startActivity(intent)
                        finish()
                    }
                }
                GO_HOME -> {
                    skip.setText("跳过 " + msg.arg1)
                    if (msg.arg1 <= 0) {
                        val intent = Intent(this@WelcomeActivity, MainActivity::class.java)
                        startActivity(intent)
                        finish()
                    }
                }
            }
        }
    }

    // 自定义的线程---控制倒计时
    inner class timeThread : Thread() {
        override fun run() {
            var i = 3
            while (i >= 0) {
                var msg = Message()
//                msg.what = MSG

                if(TelManage.hasTel()){
                    Log.d("1111111111",TelManage.getTel().toString())
                    msg.what = GO_HOME
                }else{
                    msg.what = GO_LOGIN
                }

                msg.arg1 = i
                handler.sendMessage(msg)
                i--
                try {
                    sleep(1000)
                } catch (e: Exception) {
                     e.printStackTrace()
                    break
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        supportActionBar?.hide()
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
        setContentView(R.layout.activity_welcome)

        if (thread == null) {
            thread = timeThread()
            thread?.start()
        }

        skip.setOnClickListener {
            if (thread != null) {
                thread?.interrupt()
                thread = null
            }

            val intent = Intent(this, LoginWechatActivity::class.java)
            startActivity(intent)
            finish()
        }
    }
}



四、启动优化

1.获取启动时间

获取启动时间1: Displayed com.mnstartopt/.SplashActivity: +955ms 通过系统获取启动时间;
adb命令获取启动时间2: adb shell am start -W com.mnstartopt/.WelcomeActivity

	参数:
     launch:COLD,WARM,HOT
     ThisTime: 925  代表最后一个Activity启动时间;
     TotalTime:925  代表所有Activity的启动时间;
     WaitTime: 977  所有时间:ams启动activity总耗时;

2.启动优化方向

  • 能延时启动就延时(懒加载,异步加载)
  • 与UI有关不能放入子线程的,把资源拆分,业务流程优化
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android优化之启动优化和黑白屏优化 的相关文章

随机推荐

  • 基于FPGA的LCD1602驱动(含代码)

    目录 LCD1602显示原理 LCD1602接口 LCD1602操作时序 1 读操作时序 2 写操作时序 LCD1602初始化 LCD1602读写数据 LCD1602显示原理 将LCD显示屏与FPGA连接之后 需要做的第一件事就是进行LCD
  • Redis底层封装细节

    日常我们程序员在使用redis做缓存的时候 很少会直接使用到RedisTemplate直接操作k v键值对 而是通过对RedisTemplate原生代码的封装 来构建我们日常便于使用习惯的代码来操作数据 这里我分享一下日常基本的对Redis
  • 【华为OD机试】矩阵元素的边界值【2023 B卷

    华为OD机试 真题 点这里 华为OD机试 真题考点分类 点这里 题目描述 给定一个N M矩阵 请先找出M个该矩阵中每列元素的最大值 然后输出这M个值中的最小值 输入描述 无 输出描述 无 备注 N和M的取值范围均为 0 100 用例1 输入
  • umi+dva+antd后台管理系统(3)---完整登录逻辑

    源码在这儿MyGithub 觉得不错留颗小星星哦 界面准备好啦 开始写登录 1 回顾一下redux是什么 redux 是一个应用数据流框架 主要解决了组件间状态共享的问题 原理是集中式管理 可以让数据更可控 react 中所有数据处理都在
  • JS加减乘除位移方法封装

    常用加减乘除等方法汇总 直接上代码 逻辑简单 代码如下 div 加减乘除位移方法汇总 div
  • 轨迹预处理(轨迹压缩)

    轨迹压缩分为在线压缩和离线压缩两类 在介绍两类压缩算法之前 本文先介绍两种 距离度量 方法 第一种距离度量方法是 垂直的欧几里得距离 如图b所示 p1 p7 p12作为压缩后的点 垂直度量 则为做垂线计算 第二种距离度量方法是 时间同步的欧
  • Dynamics CRM2011 导入解决方案报根组件插入错误的解决方法

    今天在还原一个老版本的解决方案 在导入时报根组件插入问题 Cannot add a Root Component 38974590 9322 e311 b365 00155d810a00 of type 31 because it is n
  • android: ERROR: unknown virtual device nam

    环境变量 ANDROID SDK HOME your path 设置好就没有问题了
  • 刷脸支付服务商为各行各业提供完美体验

    随着刷脸支付技术迭代更新的速度加快 其商业化应用的步伐也越来越快了 4月17日 支付宝推出第二代基于线下消费场景的刷脸支付机具 蜻蜓2 0 定价1499元 同时 新一代蜻蜓还实现了刷脸注册会员卡的功能 切中了苦于获客高成本的线下零售门店的需
  • pve 使用noVNC num lock 不同步的问题

    问题描述 在使用 pve 的noVNC 控制台 访问 WINDOWS 虚拟机时 VM 会出现num lock 状态不同步的情况 主要是由于WINDOWS 笔者这里是 SERVER2022 启动后默认关闭了 num lock 而 pve的虚拟
  • Scala中的抽象类

    1 先看下 类的层次结构 类层次结构 也称为类分类法 是一组相关的类 它们通过继承连接起来做类似的事情 层次结构的顶部可以是一个基类 它下面的所有其他类都是从中派生出来的 或者层次结构可以有多个基类 这些基类的功能稍后会在一个或多个派生类中
  • 论文阅读-Multi-attentional Deepfake Detection

    一 论文信息 题目 Multi attentional Deepfake Detection 作者团队 会议 CVPR 2021 二 背景与创新 背景 之前大多数方法将deepfake检测模型作为一个普通的二分类问题 即首先使用骨干网络提取
  • Redis面试题

    1 基本概念 1 1 常见考点 1 Redis 为何这么快 1 基于内存 2 单线程减少上下文切换 同时保证原子性 3 IO多路复用 4 高级数据结构 如 SDS Hash以及跳表等 2 为何使用单线程 因为 Redis 是基于内存的操作
  • esp32 系列芯片分类

    模组 内置芯片 Flash PSRAM 模组尺寸 mm ESP32 WROVER PCB ESP32 D0WDQ6 4M 8M 18 00 0 10 x 31 40 0 10 x 3 30 0 10 ESP32 WROVER IPEX ES
  • 微信公众号一些错误的原因错误代码41001

    微信公众号一些错误的原因错误代码41001 错误代码41001 缺少access token 碰到这种错误 请检查自己的appid和appsecret posted on 2017 05 08 18 02 baker95935 阅读 评论
  • git如何上传所有的新文件

    目的描述 新建的git项目 项目中有许多要从本地上传到git仓库的新文件 如果用git a filename的方法一个一个的添加 太费事费力 需要有命令添加所有改动 步骤 进入项目文件夹 在其中使用git bash 1 使用git clon
  • MySQL和MongoDB那些事

    什么是 MySQL 和 MongoDB MySQL 和 MongoDB 是两个可用于存储和管理数据的数据库管理系统 MySQL 是一个关系数据库系统 以结构化表格格式存储数据 相比之下 MongoDB 以更灵活的格式将数据存储为 JSON
  • VC++ CSWDirectoryListCtrl磁盘文件列表

    效果图 头文件定义 CSWDirectoryListCtrl h pragma once include afxwin h include
  • leetcode 3. 最长不含重复的子字符串的五种解法

    leetcode链接 最长不含重复的子字符串 题目描述 给定一个字符串 s 请你找出其中不含有重复字符的 最长子串 的长度 示例 1 输入 s abcabcbb 输出 3 解释 因为无重复字符的最长子串是 abc 所以其长度为 3 示例 2
  • Android优化之启动优化和黑白屏优化

    文章目录 一 启动流程 1 开机启动流程 2 app启动流程 二 启动分类 三 黑白屏优化 1 写一个xml文件 activity welcome 2 welcomeActivity类 四 启动优化 1 获取启动时间 2 启动优化方向 一