<activity
android:name=".MainActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.lesson9_activitylaunchmode.MainActivity"> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="toMainActivity"
android:text="这是MainActivity 启动MainActivity"
android:textAllCaps="false" /> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="toFirstActivity"
android:text="这是MainActivity 启动FirstActivity"
android:textAllCaps="false" /> </LinearLayout>

activity_main.xml

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <Button
android:id="@+id/backMain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="这是FirstActivity 返回MainActivity"/> <Button
android:id="@+id/toSecond"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="这是FirstActivity 启动SecondActivity"/> </LinearLayout>

first_layout.xml

 public class MainActivity extends AppCompatActivity {

     @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//打印地址
Log.e("MainActivity",this.toString());
Log.e("MainActivity", "Task id is " + getTaskId());
Toast.makeText(this,this.toString(),Toast.LENGTH_SHORT).show();
} public void toMainActivity(View v){
//显示Intent
Intent intent = new Intent(MainActivity.this,MainActivity.class);
startActivity(intent); } public void toFirstActivity(View v){
Intent intent = new Intent(MainActivity.this,FirstActivity.class);
startActivity(intent);
} @Override
protected void onRestart() {
super.onRestart();
Log.e("TAG","MainActivity onRestart");
} @Override
protected void onDestroy() {
super.onDestroy();
Log.e("TAG","MainActivity onDestroy");
}
}

MainActivity.java

 public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("FirstActivity",this.toString());
Log.e("FirstActivity", "Task id is " + getTaskId());
setContentView(R.layout.first_layout); Button backMain = (Button) findViewById(R.id.backMain);
Button toSecond = (Button) findViewById(R.id.toSecond); backMain.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,MainActivity.class);
startActivity(intent);
}
}); toSecond.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
}
}); } @Override
protected void onDestroy() {
super.onDestroy();
Log.e("TAG","FirstActivity onDestroy");
}
}

FirstActivity.java

 public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("SecondActivity",this.toString());
Log.e("SecondActivity", "Task id is " + getTaskId()); Button btn = new Button(this);
btn.setText("这是SecondActivity");
btn.setAllCaps(false); setContentView(btn);
} @Override
protected void onDestroy() {
super.onDestroy();
Log.e("TAG","SecondActivity onDestroy");
}
}

SecondActivity.java

1、standard

standard是活动默认的启动模式,在不进行显示指定的情况下,所有活动都会自动使用这种启动模式。

每当启动一个新的活动,它就会在返回栈入栈,并处于栈顶的位置。对于使用standard 模式的活动,系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。

MainActivity在不指定launchMode的情况下是默认的standard模式

从打印信息中我们就可以看出,每点击一次按钮就会创建出一个新的FirstActivity 实例。

此时返回栈中也会存在三个FirstActivity的实例,因此你需要连按三次Back键才能退出程序。

standard 模式的原理示意图

2、singleTop

当活动的启动模式指定为singleTop,在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例

我们将MainActivity的launchMode改为singleTop

连续点击启动自己

可以看到除了第一次启动的打印信息之外,不会再有新的打印信息了

因为目前FirstActivity已经处于返回栈的栈顶,每当想要再启动一个FirstActivity 时都会直接使用栈顶的活动,

因此FirstActivity 也只会有一个实例,仅按一次Back 键就可以退出程序。

当点击按钮去启动FirstActivity的时候,然后在FirstActivity中点击按钮返回MainActivity

可以看到系统创建了两个不同的MainActivity 实例,这是由于在FirstActivity 中再次启动MainActivity 时,栈顶活动已经变成了FirstActivity,

因此会创建一个新的MainActivity实例。现在按下Back 键会返回到FirstActivity,再次按下Back 键又会回到MainActivity,再按一次Back 键才会退出程序。

singleTop 模式的原理示意图

3、SingleTask

当活动的启动模式指定为singleTask,每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,

如果发现已经存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。

我们将MainActivity的launchMode改为singleTask

在FirstActivity 中启动MainActivity 时,会发现返回栈中已经存在一个MainActivity 的实例,并且是在FirstActivity 的下面,

于是会从返回栈中出栈,而MainActivity 重新成为了栈顶活动,因此MainActivity的onRestart()方法和FirstActivity 的onDestroy()方法会得到执行。

现在返回栈中应该只剩下一个MainActivity 的实例了,按一下Back 键就可以退出程序。

singleTask 模式的原理示意图:

4、SingleInstance

指定为singleInstance 模式的活动会启用一个新的返回栈来管理这个活动(其实如果singleTask 模式指定了不同的taskAffinity,也会启动一个新的返回栈)。

那么这样做有什么意义呢?想象以下场景,假设我们的程序中有一个活动是允许其他程序调用的,如果我们想实现其他程序和我们的程序可以共享这个活动的实例,应该如何实现呢?

使用前面三种启动模式肯定是做不到的,因为每个应用程序都会有自己的返回栈,同一个活动在不同的返回栈中入栈时必然是创建了新的实例。

而使用singleInstance 模式就可以解决这个问题,在这种模式下会有一个单独的返回栈来管理这个活动,不管是哪个应用程序来访问这个活动,都共用的同一个返回栈,也就解决了共享活动实例的问题。

 <activity
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".FirstActivity"
android:launchMode="singleInstance" />
<activity android:name=".SecondActivity" />

AndroidManifest.xml

我们将FirstActivity的LaunchMode改为SingleInstance

可以看到, FirstActivity的Task id 不同于MainActivity 和SecondActivity , 这说明FirstActivity确实是存放在一个单独的返回栈里的,而且这个栈中只有FirstActivity这一个活动。

然后我们按下Back 键进行返回,你会发现SecondActivity 竟然直接返回到了MainActivity ,再按下Back 键又会返回到FirstActivity,再按下Back 键才会退出程序,这是为什么呢?

其实原理很简单,由于MainActivity 和SecondActivity 是存放在同一个返回栈里的,当在SecondActivity 的界面按下Back 键,SecondActivity 会从返回栈中出栈,

那么MainActivity 就成为了栈顶活动显示在界面上,因此也就出现了从SecondActivity 直接返回到MainActivity 的情况。

然后在MainActivity 界面再次按下Back 键,这时当前的返回栈已经空了,于是就显示了另一个返回栈的栈顶活动,即FirstActivity。

最后再次按下Back 键,这时所有返回栈都已经空了,也就自然退出了程序。

singleInstance 模式的原理示意图:

Android Activity启动模式的更多相关文章

  1. Android Activity 启动模式详解

    最近有群里的朋友问我 Activity的四种启动模式分别是什么意思? 当初因为项目比较忙,草草的解释了下, Api文档中说的也只是一般,在这里就小记一下吧,以便有更多的朋友对Activity启动模式了 ...

  2. AndroidのActivity启动模式

    Activity启动模式      .概念      Activity启动模式定义了Activity启动的规则,它决定着Activity的实例创建与重用与否    .属性     Activity的启 ...

  3. Android Activity 启动模式和任务栈

    在了解了基本的Activity的生命周期后,我们能够很好的在一个Activity上面做相关的业务.但是这是不够的,因为Android通过任务栈来保存整个APP的Activity,合理的调度任务栈才能够 ...

  4. 详解Android Activity启动模式

    相关的基本概念: 1.任务栈(Task)   若干个Activity的集合的栈表示一个Task.   栈不仅仅只包含自身程序的Activity,它也可以跨应用包含其他应用的Activity,这样有利于 ...

  5. android:Activity启动模式之singleTask(一)

    先看一下standard启动模式的说明: 仅仅有一个实例.在同一个应用程序中启动他的时候.若不存在此Activity实例.则会在当前栈顶创建一个新的实例.若存在,则会把栈中在其上的其他Activity ...

  6. android activity 启动模式

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 1,标准的, 2,单个 顶部 3,单个 任务 4,单个 实例 标准的 就是 每启动一次这 ...

  7. Android中Activity启动模式详解

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

  8. 【转】Android总结篇系列:Activity启动模式(lauchMode)

    [转]Android总结篇系列:Activity启动模式(lauchMode) 本来想针对Activity中的启动模式写篇文章的,后来网上发现有人已经总结的相当好了,在此直接引用过来,并加上自己的一些 ...

  9. Android组件体系之Activity启动模式解析

    本文主要分析Activity的启动模式及使用场景. 一.Activity启动模式浅析 1.standard 标准模式,系统默认的启动模式.在启动Activity时,系统总是创建一个新的Activity ...

随机推荐

  1. 浅谈Chrome V8引擎中的垃圾回收机制

    垃圾回收器 JavaScript的垃圾回收器 JavaScript使用垃圾回收机制来自动管理内存.垃圾回收是一把双刃剑,其好处是可以大幅简化程序的内存管理代码,降低程序员的负担,减少因 长时间运转而带 ...

  2. [jQuery编程挑战]005 使用最短的代码生成元素的闪烁效果

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="utf-8&quo ...

  3. 用Raphael在网页中画圆环进度条

    原文 :http://boytnt.blog.51cto.com/966121/1074215 条状的进度条我们见得太多了,实现起来比较简单,它总是长方形的,在方形的区域里摆 放就不太好看了.随着cs ...

  4. [转载]windows下安装Python虚拟环境virtualenvwrapper-win

    1 前言 由于Python的版本众多,还有Python2和Python3的争论,因此有些软件包或第三方库就容易出现版本不兼容的问题. 通过 virtualenv 这个工具,就可以构建一系列 虚拟的Py ...

  5. uboot总结:uboot配置和启动过程1(主Makefile分析)

    说明:文件位置:在uboot的目录下,文件名为:Makefile 从文件的头部开始分析 1.24-29行,配置uboot的版本信息. VERSION = PATCHLEVEL = SUBLEVEL = ...

  6. 独家分享——大牛教你如何学习Web前端开发

    2014-12-18 14:35:42     引语 自从2008年接触网站开发以来到现在已经有六个年头了,今天偶然整理电脑资料看到当时为参加系里面一个比赛而做的第一个网站时,勾起了在这网站开发道路上 ...

  7. Java中传参的值传递和引用传递问题(转)

    今天遇到了一个java程序,需要用参数来返回值(虽然最后用另一种方法实现了),在网上看到这样一篇文章,很受启发. 本文章来自于http://hi.baidu.com/xzhilie/blog/item ...

  8. 转:misc_register、 register_chrdev 的区别总结

    杂项设备(misc device) 杂项设备也是在嵌入式系统中用得比较多的一种设备驱动.在 Linux 内核的include/linux目录下有Miscdevice.h文件,要把自己定义的misc d ...

  9. I2C转UART

    I2C转UART,51单片机普通IO口模拟I2C从机,解决UART不够的问题 /************************************************************ ...

  10. js eval()函数 接收一个字符串,做为js代码来执行。 如: s='var d="kaka"'; 或者s=‘function (code){return code }’;

    eval函数接收一个参数s,如果s不是字符串,则直接返回s.否则执行s语句.如果s语句执行结果是一个值,则返回此值,否则返回undefined. 需要特别注意的是对象声明语法“{}”并不能返回一个值, ...