Activity小结

Activity是一个应用组件, 单个的Activity代表一个单独的屏幕界面,用户可与其提供的屏幕进行交互。

一、任务和返回栈

一个应用通常包含多个Activity,Android系统使用任务(Task)来管理这些Activity,一个任务就是一组存放在栈里的Activity的集合,这个栈也叫做返回栈,Activity 按照各自的打开顺序排列在栈(即返回栈)中。
  任务(Task)是可以跨应用的,这正是任务存在的一个重要原因。有的Activity,虽然不在同一个应用中,但为了保持用户操作的连贯性,把他们放在同一个任务中。例如,在我们的应用中的一个Activity A中点击发送邮件,会启动邮件程序的一个Activity B来发送邮件,这两个activity是存在于不同应用中的,但是被系统放在一个任务中,这样当发送完邮件后,用户按back键返回,可以返回到原来的Activity A中,这样就确保了用户体验。


返回栈

  我们知道,栈是一种“后进先出”的数据结构,默认情况下,每创建一个新的Activity,它会在返回栈中入栈,并处于栈顶位置。当我们按下返回按钮或者调用finish()销毁栈顶活动时,位于栈顶的活动出栈,前一个栈即成为新的栈顶。系统总是会显示处于栈顶的Activity给用户。

二、Activity 生命周期

(1)Activity的四种状态

Activity在其生命周期中最多有四种状态:

  • 运行状态
    当一个Activity位于返回栈的栈顶时,该Activity就处于运行状态。
  • 暂停状态
    当一个Activity不处于栈顶位置但仍可见时,该Activity就处于暂停状态。例如,若一个Activity被一个弹出的未占满屏幕的对话框Activity遮住了,但是未完全遮住,则此时该Activity就处于暂停状态
  • 停止状态
    当一个Activity不再处于栈顶位置且完全不可见时,该Activity就处于停止状态
  • 销毁状态
    当一个Activity从返回栈中移除后就进入了销毁状态。
      以上四种状态的Activity,为了保证手机内存充足,系统最倾向于回收销毁状态的Activity,其次是处于停止状态的Activity,对于可见状态(暂停状态和运行状态)的Activity,只有在内存极低的情况下系统才会考虑回收,且系统最不愿意回收处于运行状态的Activity,因为此时的Activity正与用户直接交互,若强行回收会带来极差的用户体验。

(2)Activity的七种回调方法

Activity的生命周期

如上图所示,Activity类定义了七个回调方法来表示Activity生命周期的不同环节:

  • onCreate()
    在Activity第一次被创建的时候调用。
  • onStart()
    当Activity由不可见变为可见状态时调用。
  • onResume()
    当Activity准备好与用户进行交互时调用。此时活动一定处于运行状态,且位于返回栈栈顶。
  • onPause()
    在系统准备去启动或者恢复另一个Activity时调用。该方法一般用于保存一些关键数据以及释放掉一些消耗CPU的资源。
  • onStop()
    在Activity完全不可见时调用。
  • onDestory()
    在Activity被销毁之前调用。之后Activity即变为销毁状态。
  • onRestart()
    在Activity由停止状态变为运行状态之前调用,也即Activity被重新启动了

(3)Activity的三种生存期

以上七个方法中,出了onRestart()方法,其他方法都是两两对应的,我们可以将Activity分为三种生存期:
(1)完整生存期:onCreate()<-->onDestory()
(2)可见生存期:onStart()<-->onStop()
(3)前台生存期:onResume()<-->onPause()

(4)Activity的几种典型生命周期变化

我总结了几种典型情况下Activity的生命周期的变化:

  • Activity第一次被创建时依次执行:
    onCreate()-->onStart()-->onResume()
  • Activity被另一个Activity遮挡时(完全遮挡)依次执行:
    onPause()-->onStop()
  • 然后按下back键返回上一个Activity:
    onRestart()-->onStart()-->onResume()
  • 打开另一个对话框形式的Activity(部分遮挡):
    onPause()-->按下back键返回-->onResume()
  • 按下back键退出程序:
    onPause()-->onStop()-->onDestroy()

(5)Activity被回收的处理
  在 Activity 生命周期中,Android 会在销毁 Activity 之前调用onSaveInstanceState(),以便保存有关应用状态的数据。

@Override
    public void onSaveInstanceState(Bundle savedInstanceState)
    {
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putString("message", text.getText().toString());
    }

我们可以在onCreate()中取出Activity销毁之前保存的数据来恢复 Activity 状态。

@Override
protected void onCreate(Bundle savedInstanceState)
 {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if(savedInstanceState != null)
      {
         String message = savedInstanceState.getString("message");
      }
 }

除了在onCreate()中恢复外,我们还可以使用onRestoreInstanceState()函数来恢复数据,如下所示:

@Override
public void onRestoreInstanceState(Bundle savedInstanceState)
{
    super.onRestoreInstanceState(savedInstanceState);
    String message = savedInstanceState.getString("message");
}

需要注意的是,onSaveInstanceState()和onRestoreInstanceState()并不同于Activity的生命周期方法,它们并不一定会被触发。
  例如,当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。
  而onRestoreInstanceState()被调用的前提是,Activity确实被系统销毁了,而不是有可能被销毁。例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到Activity A,这种情况下Activity A一般不会因为内存的原因被系统销毁,故Activity A的onRestoreInstanceState()方法不会被执行。
  通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。

三、Activity的启动模式

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

<activity android:name=".MainActivity"  
          android:label="@string/title_name"  
          android:theme="@android:style/Theme.Holo.Light"  
          android:launchMode="singleTask"  
</activity> 
  • standard 标准模式,每次都新建一个实例对象
  • singleTop 如果在任务栈顶发现了相同的实例(注意是栈顶),则调用原来栈顶实例的onNewIntent()方法来重用该实例,而不是新建一个实例。否则新建并压入栈顶
  • singleTask 如果在任务栈中发现了相同的实例,将其上面的任务终止并移除,重用该实例。否则新建实例并入栈
  • singleInstance 允许不同应用,进程线程等共用一个实例,无论从何应用调用该实例都重用

为了便于理解,特意画了几张示意图说明:
(1)standard:每次激活Activity时(startActivity),都创建Activity实例,并放入任务栈。

standard模式

从图中可以看出,虽然当前栈顶为Activty2,但若再开启一个Activity2仍然会新建一个实例压入栈中成为新的栈顶。这种模式其实并不合理,每次都新建一个实例实在是浪费。事实上,我们可以根据实际情况采用下面的三种方式来进行优化。

(2)singleTop:如果某个Activity自己激活自己,即任务栈栈顶就是该Activity,则不需要创建,其余情况都要创建Activity实例。

singleTop模式

采用这种模式可以很好地解决重复栈顶的问题,但是若活动并不处于栈顶,还是会重复创建多个实例。有没有办法可以让整个应用程序的上下文只存在某个Activity的一个实例呢?这就要用到singleTask模式了。

(3)singleTask:如果要激活的那个Activity在任务栈中存在该实例,则不需要创建,只需要把此Activity放入栈顶,并把该Activity以上的Activity实例都从栈中移除。

singleTask模式

从上图中可以看到,当前栈顶为Activity3,开启Activity1,此时栈中存在Activity1,则将Activity1上面的Activity3、Activity2移除,使Activity1成为新的栈顶。
  singleTop和singleTask看起来已经可以解决大部分重复创建实例的问题了。但是,若某个应用的某个Activity频繁被其他应用调用,那么情况又会怎样呢?我们知道,每个应用都会有自己的返回栈,同一个Activity被不同应用调用,必然会在不同应用的返回栈中都创建新的实例,而使用singleInstance就可以解决这个问题了。

(4)singleInstance:如果应用1的任务栈中创建了MainActivity实例,如果应用2也要激活MainActivity,则不需要创建,两应用共享该Activity实例;


singleInstance模式

从上图中可以看到,Activity3存放在一个单独的返回栈里,在singleInstance中,会有一个单独的返回栈来管理某个被其他应用频繁调用的Activity,不管哪个应用来访问这个Activity,都共用同一个返回栈,这也就解决了应用间共享Activity实例的问题。

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

推荐阅读更多精彩内容