转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/5233269.html

先介绍下Android对Activity的管理,Android采用Task来管理多个Activity,当我们启动一个应用时,Android就会为之创建一个Task,然后启动这个应用的入口Activity(即<intent-filter.../>中配置为 MAIN和LAUNCHER的Activity)。

因为Android并没有为Task提供API,因此我们无法真正去访问Task,只能调用Activity的getTaskId()方法来获取它所在的Task的ID。事实上我们可以把Task理解成Activity栈,Task以栈的形式来管理Activity:先启动的Activity被放在Task栈底,后启动的Activity被放在Task栈顶。

那么Activity的加载模式,就负责管理实例化、加载Activity的方式、并可以控制Activity与Task之间的关系。

Activity有4中启动模式,分别为:standard,singleTop,singleTask,singleInstance。如果要使用这四种启动模式,必须在manifest文件中<activity>标签中的launchMode属性配置,如:

<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="standard"
>

</activity>

standard

标准启动模式,也是Android的默认启动模式。在这种模式下启动的activity可以被多次实例化,即在一个任务中可以存在多个activity实例,每个实例都会处理一个Intent对象。如果Activity A的启动模式为standard,并且A已经启动,在A中再次启动Activity A,即调用startActivity(new Intent(this,A.class)),会在A的上面再次启动一个A的实例,即当前的栈中的状态为A-->A。

singleTop

如果一个以singleTop模式启动的activity的实例已经存在于任务栈的栈顶,那么再次启动这个activity时,不会创建新的实例,而是重用位于栈顶的那个实例,并且会调用该实例的onNewIntent()方法将Intent对象传递到这个实例中。举例来说,如果A的启动模式为singleTop,并且A的一个实例已经存在于栈顶中,那么再调用startActivity(new Intent(this,A.class))启动A时,不会再创建A的实例,而是重用原来的实例,并且调用原来实例的onNewIntent()方法。这时任务栈中还是有一个A的实例。

如果以singleTop模式启动的activity的一个实例已经存在于任务栈中,但是不在栈顶,那么它的行为和standard模式相同,也会创建多个实例。

singleTask

官方文档上称,如果一个activity的启动模式为singleTask,那么系统总会在一个新的任务的最底部(root)启动这个activity,并且被这个activity启动的其它activity会和该activity同时存在于这个新任务中。如果系统中已经存在一个这样的activity则会重用这个实例,并且调用它的onNewIntent()方法。即,这样的一个activity在系统中只会存在一个实例。

但是这种说法并不准确,采用singleTask启动目标Activity时,可分三种情况:

1、如果将要开启的目标Activity不存在,系统将会创建目标Activity实例,并将它放入Task栈顶。

2、如果将要启动的目标Activity已经位于Task栈顶,此时与singleTop模式的行为相同。

3、如果将要启动的目标Activity已经存在、但没有位于Task栈顶,系统将会把位于该Activity上面的所有Activity移出Task栈,从而使得目标Activity转入栈顶。

下面通过实例说明:

两个Activity,FirstActivity显示文本框和按钮,该按钮用于启动SecondActivity;SecondActivity显示文本框和按钮,该按钮用于启动FirstActivity。

public class FirstActivity extends Activity {TextView tv;Button btn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv=(TextView) findViewById(R.id.tv);tv.setText("Activity为:"+this.toString()+",Task ID为:"+this.getTaskId());btn=(Button) findViewById(R.id.btn);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent=new Intent(FirstActivity.this, SecondActivity.class);startActivity(intent);}});}
}

public class SecondActivity extends Activity {TextView tv;Button btn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);tv=(TextView) findViewById(R.id.tv);tv.setText("Activity为:"+this.toString()+",Task ID为:"+this.getTaskId());btn=(Button) findViewById(R.id.btn);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent=new Intent(SecondActivity.this, FirstActivity.class);startActivity(intent);}});}
}

运行该实例,系统默认启动FirstActivity,点击该界面按钮,系统以singgleTask模式打开SecondActivity ,此时Task栈中有两个Activity(从底向上):FirstActivity-->SecondActivity.

点击SecondActivity界面按钮,系统以标准模式再次启动FirstActivity,此时Task栈中有三个Activity(从底向上):FirstActivity-->SecondActivity-->FirstActivity.

在FirstActivity中再次点击按钮,系统以singleTask模式再次打开SecondActivity,系统会将位于SecondActivity上面的所有Activity移出,使得SecondActivity进入栈顶,此时Task栈中只有两个Activity(从底向上):FirstActivity-->SecondActivity.

效果图(依次):

 

  

singleInstance

总是在新的任务中开启,并且这个新的任务中有且只有这一个实例,也就是说被该实例启动的其他activity会自动运行于另一个任务中。当再次启动该activity的实例时,会重用已存在的任务和实例。并且会调用这个实例的onNewIntent()方法,将Intent实例传递到该实例中。和singleTask相同,同一时刻在系统中只会存在一个这样的Activity实例。

说明:

这种加载模式下,系统保证无论从哪个Task中启动目标Activity,只会创建一个目标Activity实例,并会使用一个全新的Task栈来装载该Activity实例。

当用singleInstance启动目标Activity时,分两种情况:
1、当将要启动的目标Activity不存在,系统会先创建一个全新的Task、再创建目标Activity的实例,并将它加入新的Task的栈顶。

2、如果将要启动的目标Activity已经存在,无论它位于哪个应用程序中,无论它位于哪个Task中,系统将会把该Activity所在的Task转到前台,从而使用该Activity显示出来。

采用该模式加载的Activity总是位于Task栈顶,所在Task只包含该Activity.

举例说明:

点击FirstActivity中按钮,启动SecondActivity。SecondActivity配置成singleInstance加载模式,export属性配置成true---表明该Activity可被其它应用启动。

public class FirstActivity extends Activity {TextView tv;Button btn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv=(TextView) findViewById(R.id.tv);tv.setText("Activity为:"+this.toString()+",Task ID为:"+this.getTaskId());btn=(Button) findViewById(R.id.btn);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent=new Intent(FirstActivity.this, SecondActivity.class);startActivity(intent);}});}
}

        <activityandroid:name=".SecondActivity"android:launchMode="singleInstance"android:exported="true" ><intent-filter><!--知道该Activity能响应Action为指定字符串的Intent  --><action android:name="joanna.yan.action.TEST_ACTION" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></activity>

系统启动新的Task并用新的Task加载新创建的SecondActivity实例,SecondActivity总是位于栈顶。

效果图:

 

另一个示例采用隐式Intent再次启动该SecondActivity。

代码:

public class OtherActivity extends Activity {TextView tv;Button btn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);tv=(TextView) findViewById(R.id.tv);tv.setText("Activity为:"+this.toString()+",Task ID为:"+this.getTaskId());btn=(Button) findViewById(R.id.btn);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {
Intent intent=new Intent();intent.setAction("joanna.yan.action.TEST_ACTION");startActivity(intent);}});}
}

单击OtherActivity中的按钮隐式启动singleInstance模式的SecondActivity,如果前面一个示例还未退出,无论SecondActivity所在Task是否位于前台,系统将再次把SecondActivity所在Task转入前台,从而将SecondActivity显示出来。

效果图:

 

如果此文对您有帮助,微信打赏我一下吧~

Android Activity的4种启动模式详解(示例)相关推荐

  1. Activity的5种启动模式详解(新增singleInstancePerTask类型)

    前言 看到这个标题的时候,也许你会认为我写错了,Activity不是只有四种启动模式吗?分别为startard,singleTop,singleTask,singleInstance这四种. 一般来说 ...

  2. Android Activity:四种启动模式,Intent Flags和任务栈(转自他人博客)

    在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.那各个页面跳转关系如何决定呢?如果启动了顺序启动了ABCD的Activiy,如何从D调回 ...

  3. Activity生命周期及启动模式详解

    1.Activity生命周期 1.正常情况: (1) onCreate: 表示 Activty 正在被创建,这是 Activity 生命周期的第一个方法,可以做一些初始化的工作,比如:加载布局,绑定控 ...

  4. 活动的四种启动模式详解

    android:launchMode 目录 android:launchMode 前言 概念说明 standard singleTop singleTask singleInstance Codes演 ...

  5. UEFI与 Legacy BIOS两种启动模式详解

    参考链接1 参考链接2 (1). UEFI启动模式 与 legacy启动模式 legacy启动模式: 就是这么多年来PC一直在使用的启动方式(从MBR中加载启动程序),UEFI BIOS作为一种新的B ...

  6. 【OS基础】UEFI与 Legacy BIOS两种启动模式详解

    uefi和legacy是两种不同的引导方式,uefi是新式的BIOS,legacy是传统BIOS.你在UEFI模式下安装的系统,只能用UEFI模式引导:同理,如果你是在Legacy模式下安装的系统,也 ...

  7. Android系统(187)---最易懂的Activity启动模式详解

    Android基础:最易懂的Activity启动模式详解 前言 Android基础中,Activity的启动模式非常重要 本文将全面介绍 Activity的启动模式 目录 目录 1. 定义 即Acti ...

  8. Android Activity Launch Mode 启动模式详解

    简介 android:launchMode 属性能设置 Activity 对象启动时是否使用已有的实例还是多次创建,会使得交互设计更加良好,也能避免很多问题. 它是 Androidmanifest.x ...

  9. Android中Activity启动模式详解

    在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. An ...

最新文章

  1. 在哪里能收到python实例代码-python实例代码
  2. 用户添加页面html,HTML用户注册页面设置源码
  3. java 删除list元素_JAVA中循环删除list中元素的方法总结
  4. 香帅的北大金融学课笔记11 -- 资产配置
  5. .html(),.text()和.val()的差异总结
  6. android studio lambda插件,Android Studio Lambda插件(gradle-retrolambda)安装
  7. 看看80万程序员怎么评论:前端程序员会不会失业?
  8. Java多线程学习二十三:什么是阻塞队列
  9. EOS Nation更新“flash.sx遭攻击”进展:将建议MSIG根据快照将资金退还
  10. Windows批处理命令学习笔记(1)
  11. jupyter notebook怎么画决策树图_状态图怎么画?图文详解快速上手UML图
  12. 谈谈jdmailgate邮件wg在企业中的角色扮演
  13. Fiddler Everywhere 3.2.1 Crack
  14. 主流微信编辑器对比,最好用的竟然是它!
  15. erp系统软件的三层定义
  16. COSMIC度量知识整理
  17. 互联网单点登录集成方案
  18. 国内芯片60个细分领域知名代表企业
  19. 2017年4月24号课堂笔记
  20. 数据处理--图片像素点聚类

热门文章

  1. 朴素Bayse新闻分类实践
  2. 蛮力法在字符串匹配问题中的应用(JAVA)--朴素模式匹配算法
  3. GoCD notes
  4. Python的元组被设计成不可变的影响
  5. ZuulFilter的使用场景
  6. manchi翻译中文 mi_求这一段意大利文歌词中文翻译(Mi Manchi)
  7. 异常处理python 空气质量问题_python的异常处理
  8. mysql四种事务级别_【MySQL 知识】四种事务隔离级别
  9. 给即将35岁的产品经理提个醒
  10. 系统间数据传输,产品经理视角的9千字总结:接口、otter、log4j、SFTP、MQ……...