Activity 四种启动模式

前言

当我们启动安卓应用程序时,就会对应的启动这个应用程序对应的入口Activity,而这个Activity又可以启动很多个不同的Activity,系统通过任务栈来管理这些被启动Activity,栈是一种先进后出的的数据集合,每次创建一个Activity实例,系统都会将这个实例压入对应的任务栈顶,假如要是多次启动同一个Activity的话,对应的任务栈内就被压入多个此Activity的实例,造成极大的内存浪费。这种做法显然不合理,对此Android提供四种Activity启动模式来修改系统这一默认行为。这四种启动模式分别为:standardsingleTopsingleTasksingleInstance。配置形式:android:launchMode="standard / singleTop / singleTask / singleInstance",这里我们逐一对四种启动模式进行讲解。

standard

standard 即标准模式,这是系统的默认启动模式,在不指定启动模式的情况下,系统默认使用此模式启动Activity。当使用这个模式的时候,每启动一个Activity都会重复创建一个此Activity的实例,而不管当前任务栈中是否有此Activity的实例。

这里我们新建立一个StandardActivity 类,配置启动模式为standard ,在布局文件当中添加一个按钮控件,并在StandardActivity中添加这个按钮响应点击事件的方法,里面代码为从自身跳转到自身的代码,然后在onCreate方法中加上打印hashCode的日志。

<activity android:name=".StandardActivity" android:launchMode="standard"/>
Log.i("==onCreate==","StandardActivity hashCode: "+ StandardActivity .this.hashCode());
Intent intent = new Intent(this,StandardActivity.class);
startActivity(intent);
1.png

输出日志如下:
2.png

从日志可见每次启动的Activity的实例都不是同一个,也就是在该模式下,每次启动同一个Activity,都会重复创建此Activity的实例对象。

singleTop

singleTop 即栈顶单一实例模式,在设置了此模式的情况下,如果栈顶有被启动的Activity的实例,那么这个Activity不会再次创建新的实例压入栈顶,而是调用栈顶实例的onNewIntent 方法传入构建的Intent对象,实现Activity的复用,如果栈顶没有此Activity的实例,则创建此Activity的实例压入栈顶。

新建SingleTopActivity类,清单文件此Activity添加launchMode为singleTop,布局文件添加按钮,按钮的点击事件中实现自己跳转自己的代码,在onCreate方法中添加打印日志。重写onNewIntent方法,里面添加打印日志的代码。新建FristActivity 类作为程序的入口类,里面添加跳转到SingleTopActivity的代码逻辑。

<activity android:name=".SingleTopActivity" android:launchMode="singleTop"/>

SingleTopActivity类:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_singletop);
    Log.i("==onCreate==","SingleTopActivity hashCode: "+SingleTopActivity.this.hashCode());
}

// 按钮点击事件
public void goToMySelf(View view) {
    Intent intent = new Intent(this,SingleTopActivity.class);
    startActivity(intent);
}

@Override
protected void onNewIntent(Intent intent) {
    Log.i("==onNewIntent=="," SingleTopActivity-onNewIntent hashCode: "+SingleTopActivity.this.hashCode());
    super.onNewIntent(intent);
}

FristActivity 类:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_frist);
    Log.i("==onCreate==","FristActivity hashCode: "+ FristActivity.this.hashCode()+"");
}
    
public void goToSingleTopActivity(){
    Intent intent = new Intent(this,SingleTopActivity.class);
    startActivity(intent);
}

这里首先启动FristActivity ,然后启动SingleTopActivity,启SingleTopActivity后,再次从SingleTopActivity本身启动了两次SingleTopActivity,然后返回至FristActivity再次启动SingleTopActivity后,从日志当中可以看出,当SingleTopActivity处于栈顶的时候,再次启动SingleTopActivity 它的hashCode值是一样的,回调的是onNewIntent方法而不是onCreate方法,当返回至FristActivity时,FristActivity就处于栈顶,再次启动SingleTopActivity后,因为当前栈顶实例是FristActivity ,从后面两行日志可以看出,系统就重新创建了SingleTopActivity的实例。

日志输出:
3.png

singleTask

singleTask 即栈内单一实例模式,在设置了该模式的情况下,如果当前任务栈内有新启动的Activity的实例,则把这个实例移至栈顶,处于此实例上方的其他Activity实例全部移除当前任务栈,如果当前任务栈没有此实例,则创建Activity实例压入栈顶。

新建SingleTaskActivity 和FristActivity 两个类,具体代码如下。我们从FristActivity 启动SingleTaskActivity 过后,跳转回FristActivity 再次启动SingleTaskActivity 这样循环两次。

清单文件配置:

<activity android:name=".SingleTaskActivity" android:launchMode="singleTask"/>

SingleTaskActivity类:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_singletask);
    Log.i("==onCreate==","SingleTaskActivity hashCode: "+SingleTaskActivity.this.hashCode());
}

@Override
protected void onNewIntent(Intent intent) {
    Log.i("==onNewIntent==","SingleTaskActivity-onNewIntent hashCode: "+SingleTaskActivity.this.hashCode());
    super.onNewIntent(intent);
}

public void toFristActivity(View view) {
    Intent intent = new Intent(this,FristActivity.class);
    startActivity(intent);
}

FristActivity 类:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_frist);
    Log.i("==onCreate==","FristActivity hashCode: "+FristActivity.this.hashCode());
}
public void toSingleTaskActivity(View view) {
    Intent intent = new Intent(FristActivity.this,SingleTaskActivity.class);
    startActivity(intent);
}

日志输出如下:
4.png

从日志当中可以看见,除了FristActivity的hashCode一直在变化外,SingleTaskActivity 的hashCode一直都相同,而且SingleTaskActivity只调用了一次onCreate方法,其余都是回调onNewIntent 方法实现Activity的复用。由于每次需要跳转到FristActivity,导致SingleTaskActivity的实例被多次压入FristActivity实例的下方,由此可以证明在当前任务栈如果存在设置了singleTask启动模式的Activity实例,那么当再次启动此Activity时会回调onNewIntent方法实现Activity的复用。

singleInstance

singleInstance 即全局单例模式,该模式比较特殊,它具有singleTask模式的全部特性,同时设置启动模式为此模式的Activity只能单独位于一个任务栈中,也就是它不与其他Activity实例共用一个任务栈,而是自己独占一个任务栈,整个系统之中就此一个实例。当设置了此模式的新的Activity被启动时,如果当前系统中有此Activity实例的任务栈,系统就重用此实例,如果系统中没有此Activity实例的任务栈,则重新创建一个新的任务栈然后把此Activity的实例压入栈中。

新建FristActivity类和SingleInstanceActivity类。然后新建一个项目,里面添加一个可以通过隐式跳转到SingleInstanceActivity的按钮的点击事件。首先启动本应用的FristActivity类,跳转到SingleInstanceActivity中,然后再次跳转到FristActivity后,再重新跳转回SingleInstanceActivity,然后打开新建的app,跳转到SingleInstanceActivity中。

清单文件配置:

<activity android:name=".SingleInstanceActivity" android:launchMode="singleInstance"/>

本应用的SingleInstanceActivity 类:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_singleinstance);
    Log.i("==onCreate==","SingleInstanceActivity hashCode: "+SingleInstanceActivity.this.hashCode());
}
@Override
protected void onNewIntent(Intent intent) {
    String data = intent.getStringExtra("result");
    Log.i("==onNewIntent==","SingleInstanceActivity-onNewIntent hashCode: "+this.hashCode()+"data:"+data);
    super.onNewIntent(intent);
}
public void toFristActivity(View view) {
    Intent intent = new Intent(this,FristActivity.class);
    startActivity(intent);
}

本应用的FristActivity 类:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_frist);
    Log.i("==onCreate==","FristActivity hashCode: "+FristActivity.this.hashCode());
}
public void toSingleTaskActivity(View view) {
    Intent intent = new Intent(this,SingleInstanceActivity.class);
    intent.putExtra("result","本身应用的FristActivity跳转过来");
    startActivity(intent);
}

另外一个应用,具备跳转到SingleInstanceActivity方法的MainActivity 类:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Log.i("==新app-MainActivity==","MainActivity hashCode: "+this.hashCode());
}

public void toSingleInstanceActivity(View view) {
    Intent intent = new Intent("SingleInstanceActivity");
    intent.putExtra("result","新的应用APP跳转过来");
    startActivity(intent);
}

日志输出如下:
5.png

从日志当中可以看出,当第一次从FristActivity跳转至SingleInstanceActivity时调用了SingleInstanceActivity的onCreate方法,第二次从FristActivity跳转至SingleInstanceActivity时,调用了onNewIntent方法,实现了SingleInstanceActivity的复用,并打印日志说明是从本身应用跳转的,然后打开新建的应用跳转至SingleInstanceActivity时,依旧是调用的onNewIntent方法,而不是onCreate方法,并且在日志中也显示出是从新建的app跳转至SingleInstanceActivity,由此可以说明在设置了singleInstance模式的情况下,启动此Activity后,全局就此一个实例,并且独占一个任务栈。

到此Activity的四种启动模式就讲完了,其中有什么不足的地方还望大家指正。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容