冷启动与热启动,AsyncTask,HandlerThread,IntentService,Service 保活,IntentService

简介: 冷启动与热启动,AsyncTask,HandlerThread,IntentService,Service 保活,IntentService

说下冷启动与热启动是什么,区别,如何优化,使用场景等。



app冷启动: 当应用启动时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用, 这个启动方式就叫做冷启动(后台不存在该应用进程)。冷启动因为系统会重新创建一个新的进程分配给它,所以会先创建和初始化Application类,再创建和初始化MainActivity类(包括一系列的测量、布局、绘制),最后显示在界面上。


app热启动: 当应用已经被打开, 但是被按下返回键、Home键等按键时回到桌面或者是其他程序的时候,再重新打开该app时, 这个方式叫做热启动(后台已经存在该应用进程)。热启动因为会从已有的进程中来启动,所以热启动就不会走Application这步了,而是直接走MainActivity(包括一系列的测量、布局、绘制),所以热启动的过程只需要创建和初始化一个MainActivity就行了,而不必创建和初始化Application

冷启动的流程


当点击app的启动图标时,安卓系统会从Zygote进程中fork创建出一个新的进程分配给该应用,之后会依次创建和初始化Application类、创建MainActivity类、加载主题样式Theme中的windowBackground等属性设置给MainActivity以及配置Activity层级上的一些属性、再inflate布局、当onCreate/onStart/onResume方法都走完了后最后才进行contentView的measure/layout/draw显示在界面上


冷启动的生命周期简要流程::


Application构造方法 –> attachBaseContext()–>onCreate –>Activity构造方法 –> onCreate() –> 配置主体中的背景等操作 –>onStart() –> onResume() –> 测量、布局、绘制显示


冷启动的优化主要是视觉上的优化,解决白屏问题,提高用户体验,所以通过上面冷启动的过程。能做的优化如下:


减少 onCreate()方法的工作量

不要让 Application 参与业务的操作

不要在 Application 进行耗时操作

不要以静态变量的方式在 Application 保存数据

减少布局的复杂度和层级

减少主线程耗时


为什么冷启动会有白屏黑屏问题?原因在于加载主题样式Theme中的windowBackground等属性设置给MainActivity发生在inflate布局当onCreate/onStart/onResume方法之前,而windowBackground背景被设置成了白色或者黑色,所以我们进入app的第一个界面的时候会造成先白屏或黑屏一下再进入界面。解决思路如下


1.给他设置 windowBackground 背景跟启动页的背景相同,如果你的启动页是张图片那么可以直接给 windowBackground 这个属性设置该图片那么就不会有一闪的效果了


<span style="color:#000000"><code><style name=``"Splash_Theme"` `parent=``"@android:style/Theme.NoTitleBar"``>`
    <item name=``"android:windowBackground"``>@drawable/splash_bg</item>`
    <item name=``"android:windowNoTitle"``>``true``</item>`
</style>`
</code></span>

  <item name="android:windowBackground">@drawable/splash_bg`


2.采用世面的处理方法,设置背景是透明的,给人一种延迟启动的感觉。,将背景颜色设置为透明色,这样当用户点击桌面APP图片的时候,并不会"立即"进入APP,而且在桌面上停留一会,其实这时候APP已经是启动的了,只是我们心机的把Theme里的windowBackground 的颜色设置成透明的,强行把锅甩给了手机应用厂商(手机反应太慢了啦)


<span style="color:#000000"><code><style name=``"Splash_Theme"` `parent=``"@android:style/Theme.NoTitleBar"``>`
    <item name=``"android:windowIsTranslucent"``>``true``</item>`
    <item name=``"android:windowNoTitle"``>``true``</item>`
</style>`
</code></span>
复制代码

3.以上两种方法是在视觉上显得更快,但其实只是一种表象,让应用启动的更快,有一种思路,将 Application 中的不必要的初始化动作实现懒加载,比如,在SpashActivity 显示后再发送消息到 Application,去初始化,这样可以将初始化的动作放在后边,缩短应用启动到用户看到界面的时间


Android 中的线程有那些,原理与各自特点:AsyncTask,HandlerThread,IntentService



AsyncTask原理:内部是Handler和两个线程池实现的,Handler用于将线程切换到主线程,两个线程池一个用于任务的排队,一个用于执行任务,当AsyncTask执行execute方法时会封装出一个FutureTask对象,将这个对象加入队列中,如果此时没有正在执行的任务,就执行它,执行完成之后继续执行队列中下一个任务,执行完成通过Handler将事件发送到主线程。AsyncTask必须在主线程初始化,因为内部的Handler是一个静态对象,在AsyncTask类加载的时候他就已经被初始化了。在Android3.0开始,execute方法串行执行任务的,一个一个来,3.0之前是并行执行的。如果要在3.0上执行并行任务,可以调用executeOnExecutor方法


HandlerThread原理:继承自 Thread,start开启线程后,会在其run方法中会通过Looper 创建消息队列并开启消息循环,这个消息队列运行在子线程中,所以可以将HandlerThread 中的 Looper 实例传递给一个 Handler,从而保证这个 Handler 的 handleMessage 方法运行在子线程中


IntentService原理:继承自Service,它的内部封装了 HandlerThread 和Handler,可以执行耗时任务,同时因为它是一个服务,优先级比普通线程高很多,所以更适合执行一些高优先级的后台任务,HandlerThread底层通过Looper消息队列实现的,所以它是顺序的执行每一个任务。可以通过Intent的方式开启IntentService,IntentService通过handler将每一个intent加入HandlerThread子线程中的消息队列,通过looper按顺序一个个的取出并执行,执行完成后自动结束自己,不需要开发者手动关闭


IntentService是Service的子类,比普通的Service增加了额外的功能。先看Service本身存在两个问题:Service不会专门启动一条单独的进程,Service与他所在应用位于同一个进程中。


Service也不是专门一条新进程,因此不应该在Service中直接处理耗时的任务。


特点:


IntentService会创建独立的worker线程来处理所有的Intent请求;

会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程的问题;


所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service;


为Service的onBind()提供默认实现,返回null;

为Service的onStartCommand提供默认实现,将请求Intent添加到队列中;


Service 保活



1.在 onStartCommand 中返回 START_STICKY(粘性的)

这种方式并不能保证 Service 不被杀死,只是提高 Service 被杀死后快速重启概率。


2.双进程守护

为后台常驻 Service 设置守护进程,相互监听对方的状态,当监测到对方被杀死后立即重启对方 Service 达到守护 service 的目的。


IntentService原理分析



普通 Service 在未指定进程的情况下和主线程运行在同一进程,并且也在主线程中,因此在这样的 Service 中做过多耗时操作也会阻塞UI线程。


IntentService 使用了 Handler 来处理发送过来的任务,调用 startService后首先会进入 onStartCommand接着我们看到 onStart方法中将 intent 封装成 Message 丢给 handler ,handler 中的 handleMessage 方法调用 onHandleIntent,我们只需要在 onHandleIntent 完成我们要做的操作即可。 我们看到 onHandleIntent 有一个自定义的注解 @WorkerThread, 添加了该注解的方法系统会自动为我们创建一个线程然后再执行 onHandleIntent 方法。


因此,IntentService 中的消息是依次执行的,如果有很多任务并发执行,这些任务都会放在消息队列中,等待前一个任务执行完成后才能执行下一个任务。


相关文章
|
监控 数据可视化 API
yolo-nas无人机高空红外热数据小目标检测(教程+代码)
yolo-nas无人机高空红外热数据小目标检测(教程+代码)
|
Docker 容器
卸载Docker
当Docker卸载残留组件时,需手动清理。执行`yum remove`移除多个Docker相关包,包括client、common和selinux版本。接着删除`/etc/systemd/system/docker.service.d`、`/var/lib/docker`和`/var/run/docker`目录。先用`yum list installed | grep docker`列出已安装包,再用`yum -y remove`卸载`docker-ce`和`docker-ce-selinux`。
437 0
|
1月前
|
人工智能 安全 API
什么是 Prompt 注入攻击?如何防止Prompt注入攻击!
本文系统讲解AI智能体中的Prompt注入攻击及其防御策略。通过实例解析攻击原理,揭示内部Prompt泄露、权限越界等风险,并提供输入过滤、分层隔离、最小权限等六大防护措施,结合PHP代码示例与SEO应用场景,强调安全设计的重要性。
224 4
|
SQL 算法 Java
Mybatis-plus超详细讲解(2022)
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。
4251 1
|
JavaScript API
Vue3中的计算属性能否动态修改
【9月更文挑战第5天】Vue3中的计算属性能否动态修改
605 10
|
运维 安全 Linux
2024 主流的开源服务器面板推荐
随着云计算和虚拟专用服务器(VPS)的普及,服务器面板工具成为了企业和个人管理服务器的得力助手。一个优秀的服务器面板不仅可以简化服务器管理任务,还可以提升工作效率和安全性。本文将为您介绍并测评几款2024年全网热门的服务器面板,包括Websoft9、宝塔、cPanel、1Panel等,帮助您找到最适合自己的管理工具。
2024 主流的开源服务器面板推荐
scrollIntoView()定位元素显示导致页面上移解决方法?
scrollIntoView()定位元素显示导致页面上移解决方法?
1137 0
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo: 微服务通信的高效解决方案
【4月更文挑战第28天】在微服务架构的发展中,服务间的高效通信至关重要。Spring Cloud Dubbo 提供了一种基于 RPC 的通信方式,使得服务间的调用就像本地方法调用一样简单。本篇博客将探讨 Spring Cloud Dubbo 的核心概念,并通过具体实例展示其在项目中的实战应用。
414 2
|
机器学习/深度学习 人工智能 算法
未来智能家居中的人工智能技术应用与挑战
在智能家居迅猛发展的今天,人工智能技术正成为其核心驱动力。本文探讨了人工智能在智能家居中的应用现状及面临的挑战,包括数据安全、用户隐私保护和技术集成等方面。
|
JavaScript Java Serverless
理解Serverless技术—FaaS和BaaS
Serverless技术—FaaS和BaaS
3405 1