Android 启动模式

深入浅出安卓启动模式和返回栈 你面试被问过安卓的四种启动模式吗?他们各自的应用场景又是什么呢。 阅读详情

Android 启动模式


首先我们来认识一下App和进程的关系

众所周知,Android下有四大组件:Activity、Service、Receiver、ContentProvider。一般开发一个应用程序,会包含多个Android组件,所以应用程序是一组组件的集合,而进程则是运行这些组件的载体。

由上面的描述,我们知道,App仅仅是静态的概念,它把Android的四大组件打包在一起,而事实上App.apk本质上也是一个ZIP压缩包,当你解压一个App的时候,它一般长这样

此处输入图片的描述

这个压缩包里面分成了几个部分:

AndroidManifest.xml — > 声明Android四大组件
class.dex — > App代码逻辑部分
res — > AppUI部分
assets — > 保留原有格式不会转换为二进制的原始文件

从上面的文件分布上也能看出Android MVC框架的端倪,最起码形式上已经将UI和代码逻辑分开了,这部分不是本博客的重点,不再展开分析。

一个App会对应多个界面,所以在AppUI部分必然有多个资源文件,这资源文件在代码逻辑部分表现为:Activity,本质上Activity是个轻量级类,在这个Activity中持有Windows的管理类,这才是重量级类,一般的框架都有个原则:一般重量级类不需要开发人员去维护,而开发人员多与轻量级类打交道,所以Android开发人员多与Activity打交道,而用户接触的UI就直接表现在Activity上。所以为了 提高用户体验,不得不提供一个回退栈来有效的维护用户体验。所以本博客讨论的就是为了用户体验而生的Task。

##回退栈
回退栈(Back Stack)只是针对Activity而言的,它是用来维护用的界面体验的,使一个Task让用户感觉就是一个应用,而无论其中的Activity是否来自同一个应用程序,所以不要把回退栈和进程弄混了。设备的Home页面是大多数Task的起始位置,当用户点击一个应用程序图标的时候,应用的Task就会来到前台,并把应用的主Activity压入BackStack的栈顶,并获得焦点,这个Activity称为根Activity,而在BackStack中的Activity可以通过点击回退键弹出栈并销毁,这时就会使上一个Activity获得焦点,直到用户返回到Home页,而当BackStack中的Activity都被弹出销毁之后,这个Task就不复存在了,但是这个程序的进程还存在(不在此时销毁)。

##Task
就像上面介绍的,每个Task都存在一个BackStack,而系统中可以存在多个Task,但是每次只有一个Task获得前台焦点,一般而言,系统允许用户在多个Task中切换,而被至于后台的Task中的Activity,将被置于Stopped状态。实际上,同一个Task中的Activity,只要不存在于栈顶并且获得前台焦点的Activity,那么它就是一个Stopped的状态。下图为官方文档中关于Task前后台的示例图:

此处输入图片的描述

##Activity启动模式
根据Activity的不同的启动模式,它在BackStack中的状态是不一样的。Activity可以通过AndroidManifest.xml清单文件配置,在节点中的android:launchMode属性设置。它有四个选项:

  • standard
  • singleTop
  • singleTask
  • singleInstance

###standard
标准启动模式,也是默认启动模式,如果不设置android:launchMode属性的话。standard模式下的Activity会依照启动的顺序压入BackStack中。

下图是standard模式下,Activity的压栈和回退操作示意图:
  
此处输入图片的描述

###singleTop
单顶模式,这种Activity启动模式,启动一个Activity的时候如果发现BackStack的栈顶已经存在这个Activity了,就不会去重新创建新的Activity,而是复用这个栈顶已经存在的Activity,避免同一个Activity被重复开启。

下图是singleTop模式下,Activity的压栈和回退操作示意图:

此处输入图片的描述

singleTop的应用场景很多,一般适用于可以复用而又有多个开启渠道的Activity,避免当一个Activity已经开启并获得焦点后,再次重复开启。比如说Android系统浏览器的书签页面,就是一个singleTop模式的Activity。Android的浏览器是基于WebKit内核编写的,它是支持JavaScript脚本语言的,可以通过JavaScript脚本设置浏览器书签,这样如果存在多个页面存在保存书签的JavaScript脚本,就会导致书签页面被多次开启,所以书签页面被设置为singleTop模式,这样可以避免在保存多个书签的时候重复开启书签页面。

###singleInstance
被标记为singleInstance启动模式的Activity,在启动的时候,会开启一个新的BackStack,这个BackStack里只有一个Activity的实例存在,并且把这个BackStack获得焦点。这是一种很极端的模式,它会导致整个设备的操作系统里,只会存在一个这个Activity示例,无论是从何处被启动的。

下图是singleInstance模式下,Activity的压栈和回退操作示意图:

此处输入图片的描述

singleInstance一般适用于需要在系统中只存在一个实例的场景,比如Android系统的来电页面,多次来电均使用的是一个Activity。

###singleTask
上面三个启动模式都比较好理解,剩下的这个singleTask比较难理解,我们放在最后压轴说一下:

先看一下Android developer是如何说的
http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html

The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent() method, rather than creating a new instance. Only one instance of the activity can exist at a time.

它明确说明,以"singleTask"方式启动的Activity,全局只有唯一个实例存在,因此,当我们第一次启动这个Activity时,系统便会创建一个新的任务,并且初始化一个这样的Activity的实例,放在新任务的底部,如果下次再启动这个Activity时,系统发现已经存在这样的Activity实例,就会调用这个Activity实例的onNewIntent成员函数,从而把它激活起来。从这句话就可以推断出,以"singleTask"方式启动的Activity总是属于一个任务的根Activity。

但是事实上真的如此吗?

我们举个例子:

<?xml version="1.0" encoding="utf-8"?>    
<manifest xmlns:android="http://schemas.android.com/apk/res/android"    
    package="shy.luo.task"    
    android:versionCode="1"    
    android:versionName="1.0">    
    <application android:icon="@drawable/icon" android:label="@string/app_name">    
        <activity android:name=".MainActivity"    
                  android:label="@string/app_name">    
            <intent-filter>    
                <action android:name="android.intent.action.MAIN" />    
                <category android:name="android.intent.category.LAUNCHER" />    
            </intent-filter>    
        </activity>    
        <activity android:name=".SubActivity"    
                  android:label="@string/sub_activity"  
                  android:launchMode="singleTask">    
            <intent-filter>    
                <action android:name="shy.luo.task.subactivity"/>    
                <category android:name="android.intent.category.DEFAULT"/>    
            </intent-filter>    
        </activity>    
    </application>    
</manifest> 

上面manifest定义了两个Activity,这里设置了SubActivity的启动模式为singleTask模式,我们来运行这样一个程序,然后再来验证一下,这个SubActivity是不是在一个新的Task中。

当程序运行起来,并且跳转到SubActivity以后在cmd中输入

adb shell dumpsys activity 
Running activities (most recent first):  
    TaskRecord{4070d8f8 #3 A shy.luo.task}  
      Run #2: HistoryRecord{406a13f8 shy.luo.task/.SubActivity}  
      Run #1: HistoryRecord{406a0e00 shy.luo.task/.MainActivity}  
    TaskRecord{4067a510 #2 A com.android.launcher}  
      Run #0: HistoryRecord{40677518 com.android.launcher/com.android.launcher2.Launcher}  

图示是这样的:

此处输入图片的描述

很明显,SubActivity并没有新起一个Task,而是和原先的Activity位于同一个Task中,那么为什么和官方文档说的不同呢,需找答案需要我们阅读源代码,这里不再展开了,如果感兴趣可以阅读一下这篇博客http://blog.youkuaiyun.com/luoshengyang/article/details/6714543。
接下来,我们修改一下上面的manifest文件如下:

<?xml version="1.0" encoding="utf-8"?>    
<manifest xmlns:android="http://schemas.android.com/apk/res/android"    
    package="shy.luo.task"    
    android:versionCode="1"    
    android:versionName="1.0">    
    <application android:icon="@drawable/icon" android:label="@string/app_name">    
        <activity android:name=".MainActivity"    
                  android:label="@string/app_name"  
                  android:taskAffinity="shy.luo.task.main.activity">    
            <intent-filter>    
                <action android:name="android.intent.action.MAIN" />    
                <category android:name="android.intent.category.LAUNCHER" />    
            </intent-filter>    
        </activity>    
        <activity android:name=".SubActivity"    
                  android:label="@string/sub_activity"  
                  android:launchMode="singleTask"  
                  android:taskAffinity="shy.luo.task.sub.activity">    
            <intent-filter>    
                <action android:name="shy.luo.task.subactivity"/>    
                <category android:name="android.intent.category.DEFAULT"/>    
            </intent-filter>    
        </activity>    
    </application>    
</manifest>

然后按照上面的步骤,查看一下是不是新起了一个Task

Running activities (most recent first):  
    TaskRecord{4069c020 #4 A shy.luo.task.sub.activity}  
      Run #2: HistoryRecord{40725040 shy.luo.task/.SubActivity}  
    TaskRecord{40695220 #3 A shy.luo.task.main.activity}  
      Run #1: HistoryRecord{406b26b8 shy.luo.task/.MainActivity}  
    TaskRecord{40599c90 #2 A com.android.launcher}  
      Run #0: HistoryRecord{40646628 com.android.launcher/com.android.launcher2.Launcher}  

可以看到,的确如android 开发文档所说。

所以我们对于signalTask可以小结如下:

  • 设置了"singleTask"启动模式的Activity,它在启动的时候,会先在系统中查找属性值affinity等于它的属性值taskAffinity的任务存在;如果存在这样的任务,它就会在这个任务中启动,否则就会在新任务中启动。因此,如果我们想要设置了"singleTask"启动模式的Activity在新的任务中启动,就要为它设置一个独立的taskAffinity属性值。
  • 如果设置了"singleTask"启动模式的Activity不是在新的任务中启动时,它会在已有的任务中查看是否已经存在相应的Activity实例,如果存在,就会把位于这个Activity实例上面的Activity全部结束掉,即最终这个Activity实例会位于任务的堆栈顶端中。

本文参考

  1. http://www.cnblogs.com/plokmju/p/android_activitylaunchermode.html
  2. http://blog.youkuaiyun.com/luoshengyang/article/details/6714543
【android开发-05】android中activity的启动模式介绍 android中activity的启动模式原理和运行代码的参考例子 阅读详情

相关推荐

ResNet理论基础与具体实现(详细教程)

论文地址:Deep Residual Learning for Image Recognition ​ Identity Mappings in Deep Residual Networks pytroch源码地址:resnet 0x00 前言 ResNet是2015年就提出的网络结构,中文名字叫作深度残差网络,主要作用是图像分类。现在在图像分割、目标检测等领域都有很...

coordinate的博客 8329

Android的四种启动模式

Android的四种启动模式

weixin_44715716的博客 9017

ChatGPT Web转API工具:原理、部署与集成实战

在AI应用开发中,API(应用程序编程接口)是实现系统间通信和数据交换的核心技术,它通过标准化的请求响应机制,将复杂功能封装为可编程的服务。其工作原理基于HTTP协议,通过定义清晰的端点、方法和数据格式,使不同平台的应用能够高效集成AI能力。这一技术价值在于极大降低了开发门槛,促进了自动化流程和智能功能的快速落地,广泛应用于智能客服、内容生成和创意辅助等场景。本文聚焦于如何通过浏览器自动化技术,将ChatGPT的Web界面能力转化为标准API服务,其中涉及Playwright无头浏览器操作和会话Cookie

weixin_42533910的博客 1758

Android ---【基础篇】图解四种启动模式及实际应用场景解说

而一般onCreate方法中会进行该页面的数据初始化、UI初始化,假设页面的展示数据无关页面跳转传递的參数,则不必操心此问题,若页面展示的数据就是通过getInten() 方法来获取,那么问题就会出现:getInten()获取的一直都是老数据,根本无法接收跳转时传送的新数据!系统会为它创建一个单独的任务栈,由于栈内复用的特性。假设你在当前的Activity中又要启动同类型的Activity,此时建议将此类型Activity的启动模式指定为SingleTop,能够降低Activity的创建,节省内存!

梁同学与Android 4592

第3章 信息技术服务(一)

对 第三章 《信息技术服务》中第一、二、三节 <内涵与外延、原理与组成、服务生命周期>进行总结、归纳

好好学习,天天向上的博客 733

Comsol超声空化气泡仿真入门:从零搭建模型到网格划分的完整流程

本文详细介绍了使用Comsol进行超声空化气泡仿真的完整流程,从物理基础理解到模型搭建、网格划分及求解器设置。通过具体步骤和示例代码,帮助初学者和工程师快速掌握这一关键技术,应用于医疗设备和工业清洗等领域。

weixin_29289821的博客 161

193.Android四种启动模式

standard 模式对于大多数普通页面足够简单直接;singleTop 模式能够在频繁重复启动同一页面时避免资源浪费,并及时刷新界面;singleTask 模式适合需要全局唯一性、确保多入口归一的关键页面;singleInstance 模式提供完全独立的运行环境,适用于特定业务场景。若不需要额外的状态维护,standard 足够应付常规页面跳转;若目标页面数据需要更新且防止重复创建,则 singleTop 是不错的选择;若需要在全局范围内保证页面唯一性,singleTask 能方便管理;

2303_79132118的博客 3101

易康eCognition9.0分类|规则集和机器学习的方法的面向对象的多尺度分割分类

基于易康eCognition9.0软件的规则集和机器学习的方法的面向对象的多尺度分割分类

weixin_46493028的博客 1万+

android四种启动模式

说明:Android创建Activity时的默认模式,假设没有为Activity设置启动模式的话,默觉得标准模式。每次启动一个Activity都会又一次创建一个新的实例入栈,无论这个实例是否存在。生命周期:如上所看到的,每次被创建的实例Activity 的生命周期符合典型情况,它的onCreate、onStart、onResume都会被调用。一句话:只要点击某个类就会生成新的实例(占内存)

zxz_zxz_zxz的博客 1180

Win10家庭版没有Hyper-V?教你一招轻松解决(含避坑指南)

本文详细介绍了在Win10家庭版中启用Hyper-V的完整实战指南。通过DISM工具链绕过系统版本限制,无需重装系统即可完整启用所有Hyper-V组件,适用于开发者测试多系统环境和安全隔离应用场景。文章包含详细操作步骤、常见问题解决方案及性能优化配置,帮助用户轻松解决Win10家庭版没有Hyper-V的问题。

weixin_29239661的博客 495

在 SAP SD 模块里,销售订单号既可以由系统“自动”产生,也可以由用户“手工”输入,核心取决于“号码段(Number Range)”与“订单类型(Sales Document Type)”这两处配

SAP销售订单编号配置指南:系统提供内部自动编号和外部手工编号两种方式,通过VN01定义号码段(内部/外部),VOV8分配给订单类型并设置"ExtNo.Rq"选项即可切换。高阶应用支持灵活编号(如加前缀)或通过增强出口完全自定义编号规则。配置时需注意号码段创建、分配及传输问题,常见故障包括号码范围不存在或配置错误。核心是"号码段+订单类型"的组合控制编号生成方式,满足从简单到复杂的业务需求。

金牌架构师 531

Android的4种启动模式

Android的4中启动模式

m0_58860979的博客 679

C++笔记之emplace_back(),push_back()性能比较i++ 、 ++i

操作是否需要临时对象/拷贝性能需要(构造临时对象)较慢不需要(直接构造)较快i++需要(保存旧值)对于内置类型无影响,但对于自定义类型(如迭代器、大对象)会有拷贝开销++i不需要相对更快(尤其是自定义类型)都存在"是否需要额外的临时对象/拷贝"这一性能差异点和++i都是更高效的版本(避免临时对象/拷贝)和i++都可能产生额外的临时对象(前者构造临时对象,后者保存旧值)对于内置类型(如int),i++和++i性能几乎没有差异(编译器会优化);但对于自定义类型(尤其是迭代器等重量级对象),

小勇博客 95

安卓Android activity的启动模式

如图1.4,有三个activity,其中SecondActivity的启动模式为singleInstance,另外两个activity的启动模式为standard模式。singleTask 模式为栈内复用模式,相较于singleTop模式,singleTask 模式不是判断activity是否处于栈顶,singleTop模式为栈顶复用模式,相较于standard模式,singleTop模式不会每次都创建新的实例,而是。在不指定的情况下,Activity的启动模式默认为standard模式。

m0_54198552的博客 401

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Android安卓活动的启动模式

当启动设置为该启动模式的活动时,会先检查一遍当前栈中是否已经有该要启动的活动,如果没有则在栈顶创建一个该启动的活动,如果栈中已有这个要启动的活动,则将要启动活动上方的所有活动都统统清除出栈,这样就启动了要启动的活动。当我们启动设置为singleInstance启动模式的活动时,会直接把该活动置于一个新的栈中,而且这个新的栈还只有这一个活动。也就是标准/默认的启动模式,它不管栈中是否已经存在这个需要启动的活动,只要启动了这个活动就会创建一个新的活动实例置于栈顶。4.singleInstance启动模式。

weixin_57244464的博客 341

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Android安卓 Activity四种启动模式(launchMode) standard, singleTop, singleTask, singleInstance

启动模式的重要性 Android编程中经常涉及到页面的切换,启动一个新的页面(或者说Activity)的时候需要为其指定合适的“启动模式”。指定的启动模式不合适,会出现类似下面这种奇怪的效果: 你拿起QQ切换了一个新的账号,一直按返回却没有退出程序,而是又回到了旧帐号对应的页面… 你拍完照进相册看了一下刚刚拍的照片又退出,却发现拍照界面出现了黑屏… 这些情况的出现当然可能和其他的原因相关,...

qq_44861716的博客 2700

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Android LanuchMode 安卓下的启动模式

任务栈的概念:一般情况下,有多少个应用在运行,就对应开启多少任务栈。每开启一个应用程序,就会创建一个与之对应的任务栈。     任务栈的作用:是存放Activity引用的,Activity不同的启动模式,对应不同的任务栈的存放。可以通过getTaskId()来获取任务栈的id,如果前面的任务栈已经清空,新开的任务栈的ID+1, 是自动增长的。 启动模式: Standard: 默认,每次调用s

fckdenny的专栏 875

安卓四种启动模式

四种模式 1.Standard 默认的启动模式,设置该模式的Activity每次被启动都会重复创建该Activity的实例。 应用于大部分场景。 2.SingleTop 栈顶复用模式,设置为该模式的Activity 如果位于任务栈的栈顶则直接调用此Activity 的OnNewIntent方法,如果不位于栈顶则会重新创建该Activity的实例。 应用场景:点击通知栏的多条通知消息进入同一个页面,...

weixin_38174835的博客 2176

android activity启动模式_安卓学习笔记之Android中Activity的4种启动模式

根据Activity在任务栈中的调用方式不同,Activity的启动模式分为4种,分别是Standard、SingleTop、SingleTask以及SingleInstance。可以在AndroidManifest.xml文件的android:launchMode属性中设置。1、Standard模式:Standard模式是Android的默认启动模式。这种模式下,Activity每次启动,无论任...

weixin_39731916的博客 136

安卓活动的启动模式

安卓活动的启动模式 版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明。2019-09-23,22:05:10。作者By-----溺心与沉浮----博客园   在安卓实际项目中我们应该根据特定的需求为每个活动指定恰当的启动模式。启动模式一共有4种,分别是standard、singleTop、singleTask、singleInstance,我们可以在AndroidMani...

antangtong2499的博客 262

Android安卓-四大启动模式是什么?启动模式详解,场景运用。

转自 “逆水当行舟” 的博客,收藏记录。 启动模式 启动模式是什么 有这样的场景: 当我们使用App的时候,呈现出一个Activity,按下返回键(不考虑重写返回键事件),常常就回退到上一个打开的Activity或者退出App。 //重写返回按键事件public bo

ruiruiddd的博客 979

android的启动模式 到底在什么时候用呢?

版权声明:本文为博主原创文章,未经博主允许不得转载。 目录(?)[+] 涉及的内容一句话理解四种启动模式网上太多了 onNewIntent是什么 四种启动模式什么时候用呢把网上找的基本都测了一遍自己的感悟吧 一些常用的flag组合没写的是我很少用没有发言权呀 安卓的启动模式 估计都学过 但好长时间内不知道怎么用,感觉都忘了启动模式的存在了,一般都

阳光灿烂的日子的博客 1443

android recovery分析,安卓系统启动模式—Recovery模式英文全解析

相信很多朋友在使用手机启动模式的时候,或者各种应用的时候,对于手机中出现的各种英文一定不是很了解。下面就安卓手机系统中的重要启动模式—Recovery模式,来给大家详细英文全解析说明!众所周知,Recovery模式是Android系统中一个非常重要的启动模式,该模式下可以打开命令解释程序(shell),刷新映像文件(flash image),执行备份等。当然这一切取决于你手机上的recovery ...

weixin_36295973的博客 3294

安卓四种启动模式的经验总结

大家都知道,安卓有四种启动模式,使用的时候在清单文件配置一下就好了。但是如果你对四种启动模式认识不深,后面是要吃大亏的!有些需求场景本来是可以简单实现的,但是却被各自需求逻辑搞复杂。我之前遇到一个问题是,点击手机桌面图标,打开的Activity总是启动页,当时以为是因为我们把启动页这个Activity设置成了LauchActivity导致的,所以我把MainActivity设置成了LauchActi

阿甘正传 978

android 启动模式_安卓学习笔记之Android中Activity的4种启动模式

根据Activity在任务栈中的调用方式不同,Activity的启动模式分为4种,分别是Standard、SingleTop、SingleTask以及SingleInstance。可以在AndroidManifest.xml文件的android:launchMode属性中设置。1、Standard模式:Standard模式是Android的默认启动模式。这种模式下,Activity每次启动,无论任...

weixin_39625162的博客 168
上一篇: Android View 分析(上)
下一篇: Android 进程间通信IPC_AIDL
linroidh
博客等级 码龄16年 15粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值