配置Activity时可指定android:launchMode属性,该属性用于配置该Activity的加载模式,该属性支持如下4个属性值。

  • standard:标准模式,这是默认的加载模式。
  • singleTop:Task顶单例模式。
  • singleTask:Task内单例模式。
  • singleInstance:全局单例模式。

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

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

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

下面详细介绍这4种加载模式。

  1、standard加载模式

每次通过这种模式来启动目标Activity时,Android总会为目标Activity创建一个新的实例,并将该Activity添加到当前Task栈中——这种模式不会启动新的Task,新Activity将被添加到原有的Task中。

下面的示例使用了standard模式来不断启动自身。

package com.example.studyactivity;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView; public class StandardTest extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout=new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
this.setContentView(layout);
//创建一个TextView来显示该Activity和它所在的Task ID
TextView tv=new TextView(this);
tv.setText("Activity为"+this.toString()+"\n"+",Task ID为:"+this.getTaskId());
Button button=new Button(this);
button.setText("启动StardardTest");
//添加TextView和Button
layout.addView(tv);
layout.addView(button);
//为button添加事件监听器,当单击该按钮时启动StandardTest
button.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View v) {
// TODO Auto-generated method stub
//创建启动StardardTest的Intent
Intent intent=new Intent(StandardTest.this,StandardTest.class);
startActivity(intent);
}});
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.standard_test, menu);
return true;
} }

正如上面的粗体字代码所示,每次单击按钮,程序将会再次启动StandardTest   Activity,程序配置该Activity时无须指定launchMode属性,该Activty默认采用standard加载模式。

运行该程序,多次单击程序界面上的“启动StandardTest”按钮,程序将会不断启动新的StandardTest实例(不同Activity实例的hashCode值有差异),但它们所在的Task ID总是相同的——这表明这种加载模式不会使用全新的Task。

standard加载模式的示意图如图4.22所示。

正如图4.22所示,当用户低年级手机的“返回”键时,系统将会“逐一”从Activity栈顶删除Activity实例。

2、singleTop模式

     这种模式与standard模式基本相似,但有一点不同:当将要被启动的目标Activity已经位于Task栈顶时,系统不会重新创建目标Activity的实例,而是直接复用已有的Activity实例。

如果将上面实例中StandardTest Activity的加载模式改为standard加载模式,无论用户点击多少次按钮,界面上的程序将不会有任何变化。

如果将要比启动的目标Activity没有位于Task栈顶,此时系统会重新创建目标Activity的实例,并将它加载到Task的栈顶——此时与standard模式完全相同。

    3、singleTask模式

     采用这种加载模式的Activity在同一个Task内只有一个实例,当系统采用singleTask模式启动Activity时,可分为如下三种情况:

  • 如果将要启动的目标Activity不存在,系统将会创建目标Activity的实例,并将它加入Task栈顶。
  • 如果将要启动的目标Activity已经位于栈顶,此时与singleTop模式的行为相同。
  • 如果将要启动的目标Activity已经存在、但没有位于Task栈顶,系统将会把位于该Activity上面的所有Activity移出Task栈,从而使目标Activity转入栈顶。

   4、singleInstance模式

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

当系统采用singelInstance模式启动目标Activity时,可分为如下两种情况。

  • 如果将要启动的目标Activity不存在,系统会先创建一个全新的Task、再创建目标Activity的实例,并将它加入新的Task的栈顶。
  • 如果将要启动的目标Activity已经存在,无论它位于哪个应用程序中,无论它位于哪个Task中,系统将会把该Activity所在的Task转到前台,从而使该Activity显示出来。

需要指出的是,采用singleInstance模式加载Activity总是位于Task栈顶,采用singleInstance模式加载Activity所在Task只包含该Activity。

下面示例中的SingleInstanceTest中包含一个按钮,当用户单击该按钮时,系统启动SingleInstanceSecondTest,程序清单如下。

package com.example.studyactivity;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView; public class SingleInstanceTest extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout=new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
this.setContentView(layout);
//创建一个TextView来显示该Activity和它所在Task ID
TextView tv=new TextView(this);
tv.setText("Activity为:"+this.toString()+"\n"+",Task ID为:"+this.getTaskId());
Button button=new Button(this);
button.setText("启动SingleInstanceSecondTest");
layout.addView(tv);
layout.addView(button);
//为button添加事件监听器,当单击该按钮时启动SingleInstanceSecondTest
button.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent=new Intent(SingleInstanceTest.this,SingleInstanceSecondTest.class
);
startActivity(intent);
}});
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.single_instance_test, menu);
return true;
} }

上面的粗体字代码指定单击按钮时将会启动SingleInstanceSecondTest,将该SingleInstanceSecondTest配置成singleInstance加载模式,并且将该Activity的exported属性配置成true——表明该Activity可被其他应用启动。

配置该Activity的配置片段如下:

 <activity
android:name="com.example.studyactivity.SingleInstanceSecondTest"
android:label="@string/title_activity_single_instance_second_test"
android:exported="true"

android:launchMode="singleInstance"
>
<intent-filter> <!-- 指定该Activity能响应Action为指定字符串的Intent -->
<action android:name="com.example.intent.action.CRAZY_T_ACTION" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

配置该Activity时,将它的exported属性设为true,表明允许通过其他程序来启动该Activity,配置该Activity时还配置了<intent-filter.../>子元素,这表明该Activity可通过隐式Intent启动。

运行该示例,系统默认显示SingleInstanceTest,当用户单击该Activity界面上的按钮时,系统将会采用singleInstance模式加载SingleInstanceSecondTest:系统启动新的TaskTask、并用新的Task加载新创建的SingleInstanceSecondTest实例,SingleInstanceSecondTest总是位于该新Task的栈顶。

另一个示例将采用隐式Intent再次启动该SingleInstanceSecondTest,下面是采用隐式Intent启动SingleInstanceSecondTest的示例的代码。

package com.example.studyactivity;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView; public class SingleInstanceOtherTest extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout=new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
setContentView(layout);
//创建一个TextView来显示该Activity和它所在的Task ID
TextView tv=new TextView(this);
tv.setText("Activity为:"+this.toString()+"\n"+",Task ID为:"+this.getTaskId());
Button button=new Button(this);
button.setText("启动SingleInstanceSecondTest");
//添加TextView和Button
layout.addView(tv);
layout.addView(button);
//为button添加事件监听器,使用隐式Intent启动目标Activity
button.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View v) {
// TODO Auto-generated method stub
//使用隐式Intent启动SingleInstanceSecondTest
Intent intent=new Intent();
intent.setAction("com.example.intent.action.CRAZY_T_ACTION"
);
startActivity(intent);
}});
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.single_instance_other_test, menu);
return true;
} }

运行该示例,系统默认显示SingleInstanceOtherTest,当用户单击该Activity界面上的按钮时,系统将采用隐式Intent来启动SingleInstanceSecondTest,注意SingleInstanceSecondTest的加载模式是singleInstance,如果前一个示例还未退出,无论SingleInstanceSecondTest所在的Task是否位于前台,系统将再次把SingleInstanceSecondTest所在的Task转入前台,从而将SingleInstanceSecondTest显示出来。

Activity的生命周期与加载模式——Activity的4种加载模式的更多相关文章

  1. Activity 的生命周期与加载模式

    当Activity 处于Android 应用中运行时,它的活动状态由 Android 以 Activity 栈的形式管理.当前活动的Activity位于栈顶.随着不同应用的运行,每个Activity都 ...

  2. 十分钟掌握Activity的生命周期与启动模式

    1. Activity的生命周期 正常情况下的Activity生命周期如下图所示(来自Android Developer): 当资源相关的系统配置变更时(比如设备屏幕方向改变,键盘可见性变化),会导致 ...

  3. Activity 之生命周期

    Activity 之生命周期 本文内容: 1. Activity 介绍 2. Activity 的生命周期 2.1 生命周期图 2.2 常见情况下生命周期的回调 2.3 关于生命周期常见问题 2.4 ...

  4. 深入了解Activity-生命周期

    一 介绍 Activity是android中使用最为频繁的组件,在官方文档中是这样描述的:An activity is a single, focused thing that the user ca ...

  5. Android Activity的生命周期详解

    应用程序中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应. Activity之间通过Intent进行通信.在Intent 的描述结构中,有两个最 ...

  6. Activity的生命周期

    Activity的生命周期 以往我们实现页面间的跳转都是实例化Intent类的对象,但是页面在我们眼前的出现与消失没有我们所看到的那么简单,它有一个复杂的生命周期,一个页面的出现,被覆盖,再次出现,被 ...

  7. 浅谈Android中Activity的生命周期

    引言 我想对于Android开发人员来说,Activity是再熟悉不过了,今天我们就来探讨下Activity的生命周期.熟悉的掌握Activity对于开发健壮的Android应用程序来说至关重要.下面 ...

  8. 横竖屏切换时,Activity的生命周期

    横竖屏切换时,Activity的生命周期 1.新建一个Activity,并把各个生命周期打印出来 2.运行Activity,得到如下信息 onCreate-->onStart-->onRe ...

  9. Android 横屏切换竖屏Activity的生命周期(转)

    曾经遇到过一个面试题,让你写出横屏切换竖屏Activity的生命周期.现在给大家分析一下他切换时具体的生命周期是怎么样的:  1.新建一个Activity,并把各个生命周期打印出来  2.运行Acti ...

  10. 横竖屏切换时候Activity的生命周期的总结

    1.新建一个Activity,并把各个生命周期打印出来 2.运行Activity,得到如下信息 onCreate--> onStart--> onResume--> 3.按crtl+ ...

随机推荐

  1. jquery奇怪的问题

    Jquery中 $("#data_table4 tr:eq(0)").after("<tr><td>" +result+data.row ...

  2. Python3基础 list() 将一个字符串转换成列表

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

  3. c# 添加了按钮双击事件后,再删除掉代码会提示错误

    有两种方法:.清空属性窗口中的双击事件(doubleclick )右边的内容: .单击“发生错误”提示窗口的“否”后,再双击错误列表里的错误项,此时编辑窗口跳转为xx.Designer.cs,然后注释 ...

  4. Bundle versions string, short与Bundle version

    在提交更新的app至appstore中时,需要在**.plist中设置app的version信息.Bundle versions string, short --- CFBundleShortVers ...

  5. Java谜题——库谜题

    1.Java中的不可变对象和可变对象 (1)不可变类:当你获得这个类的实例的引用之后,你不可以改变这个实例的内容.比如:String,BigInteger,BigDecimal,还有基本数据类型的封装 ...

  6. rsync+inotify实现数据的实时备份

    一.rsync概述 1.1.rsync的优点与不足 rsync与传统的cp.tar备份方式相比,rsync具有安全性高.备份迅速.支持增量备份等优点,通过rsync可以解决对实时性要求不高的数据备份需 ...

  7. 已经安装了Myeclipse8.5 的情况下,激活myeclipse10.7要注意

    使用下载好的10.7的包里的激活文件和提供的激活方法激活,不成功,在网上搜索了很多方法试过也不成功,最后打开安装目录D:\MyEclipse 10下的myeclipse.ini文件,发现如下内容: . ...

  8. 编写一个python脚本功能-备份

    版本一 解决方案当我们基本完成程序的设计,我们就可以编写代码了,它是对我们的解决方案的实施.版本一例10.1 备份脚本——版本一 #!/usr/bin/python # Filename: backu ...

  9. (简单) POJ 2387 Til the Cows Come Home,Dijkstra。

    Description Bessie is out in the field and wants to get back to the barn to get as much sleep as pos ...

  10. (简单) HDU 1698 Just a Hook , 线段树+区间更新。

    Description: In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of ...