Activity

Activity就是用来和用户交互的界面。要使用一个Activity,就必须在AndroidManifest.xml文件中对其进行声明, 如果不想把Activity暴露给其他应用可以不添加intent filter。
Activity的状态会随着用户操作/系统回收而发生变化,这些状态由系统控制,但是开发者可以通过一系列的callback 来决定activity状态变化时的操作。


1. 正常生命周期

请看下图(来自Android官网):
Activity生命周期

onCreate() 方法中应该调用setContentView()方法将UI的layout设置好。
onCreate()方法完成之后,Activity就进入Started state,这时Activity就对用户可见了,但是由于还没有进入前台,所以用户看不到。onStart()(Activity已经可见,只是还没有进入前台,无法和用户进行交互) 方法中完成Activity进入前台以及可交互前的最后准备。
在onStart()方法完成之后,activity会进入Resumed state,并且进入前台; 在Activity和用户交互前,系统会调用 onResume() 方法, 这个时候Activity是在"activity stack"栈顶的,并且可以捕获用户所有的输入事件。

onPause() 方法的调用在onResume()方法之后。当activity失去焦点,并进入Paused state后,系统会调用onPause()方法,虽然这时activity还是部分可见的,但是往往意味着用户在离开当前的activity,activity将要进入Stoped state或者Resume state,而且已经不在前台(Multi-window mode下可能依然可见)。
Paused state的activity仍然可以更新UI。onPause()方法执行完成并不意味这activity会退出Paused state, 相反,activity会保持Paused state,直到activity resume或者完全不可见。

不应该在onPause()方法中进行保存应用/用户数据,访问网络和操作数据库等耗时操作。因为如果用户启动了另外的activity,系统会在完成当前activity的onPause()方法后才创建新activity,所以如果当前activity的onPause()方法中有耗时操作,那么新activity的启动会比较慢。可以将这些耗时操作放到onStop()方法中。

当activity 不再对用户可见 (被销毁或者被新activity覆盖)时,系统会调用activity的onStop() 方法。
在Activity被销毁之前,系统会调用onDestroy() 方法,确保activity使用的资源全部释放。

onCreate()和onDestroy()方法对应,两者在activity的生命周期都只执行一次。
onStart()和onStop()方法对应,两者都可能会执行多次。
onResume()和onPause()方法对应,两者都可能会执行多次。

当一个activity启动另外一个activity的时候,两者都会发生生命周期的转移(状态变化),但是以防两者需要共享数据/传递信息,当第二个actiivty创建的时候,第一个activity并不会直接进入Stopped state。
下面是Activity A 启动Activity B时,生命周期callback的执行情况:

  1. Activity A’s onPause() method executes.
  2. Activity B’s onCreate(), onStart(), and onResume() methods execute in sequence. (Activity B now has user focus.)
  3. Then, if Activity A is no longer visible on screen, its onStop() method executes.

2. 异常情况下的生命周期

1). 系统需要回收内存,一些优先级比较低的进程会被杀掉,运行在其中的activity会被销毁。
系统是否会杀死进程,取决于进程的状态,而进程的状态取决于运行在其中的activity状态。
这里写图片描述

2). 当系统配置发生改变,activity需要重新创建,那么activity也会被临时销毁。
由于上面的情况导致activity被销毁时,onSaveInstanceState和onRestoreInstanceState()可以用来保存数据。onSaveInstanceState()方法会在onStop()方法之前调用,但是和onPause()方法的调用顺序不固定。
onSaveInstanceState()方法中保存的数据,在activity重新创建时可以在onCreate()和onRestoreInstanceState()方法中获取,但是onCreate()是必然会调用的方法,所以需要对保存数据的bundle做非空判断,onRestoreInstanceState()方法则不用做非空判断,该方法会在onStart()方法之前调用。

3. Activity task
3.1 概述

Task中包含了一系列的activity,这些activity都为了完成同一个任务; 这些activity以栈的形式进行管理(back-stack),当stack中的activity都出栈后,task将不复存在。
这里写图片描述

如果想打破系统默认的行为,那么可以在manifest文件中对 <activity>使用下面的属性,也可以在调用startActivity()方法时使用Flag。
1). 可以使用的属性:

  • taskAffinity
  • launchMode
  • allowTaskReparenting
  • clearTaskOnLaunch
  • alwaysRetainTaskState
  • finishOnTaskLaunch

2) 可以使用的Flag:

  • FLAG_ACTIVITY_NEW_TASK
  • FLAG_ACTIVITY_CLEAR_TOP
  • FLAG_ACTIVITY_SINGLE_TOP
3.2. 启动模式
  • standard
    标准模式/默认模式,使用这种启动模式的activity,每次启动时系统都会创建新实例,这些实例可以位于不同的task,也可以是同一task。

  • singleTop
    如果被启动的activity已经在当前task的栈顶,那么系统不会创建新的实例,而是调用当前activity的onNewIntet方法将intent传递给activity; 否则,系统会创建activity新实例。

  • singleTask
    对于这种启动模式的activity, 系统在启动时,如果没有对应的task存在,那么系统会创建新task和新实例,并将这个实例作为新task的root activity; 如果已经有对应的task存在,分两种情况:

  1. task存在,但是activity不存在;系统会创建新activity实例。
  2. task存在,activity也存在; 系统会将activity之上的activity出栈,并调用activity的onNewIntent方法。
  • singleInstance
    启动时和singleTask一样,但是系统不会将其他activity放入对应的task中,即当前activity是task中的唯一实例。

3.3. 启动Flag
  • FLAG_ACTIVITY_NEW_TASK
    和”singleTask“的作用一样

  • FLAG_ACTIVITY_SINGLE_TOP
    和"singleTop"的作用一样

  • FLAG_ACTIVITY_CLEAR_TOP
    如果目标activity已经在当前的task中,那么系统不会启动新的activity,而是将栈中activity之上的activity全部出栈,然后调用目标activity的onNewIntent方法。
    这个flag常和FLAG_ACTIVITY_NEW_TASK一块使用,可以用来定位在其他task中存在的目标activity,并将它放在可以处理intent的位置(也就是栈顶呗)。
    如果目标activity的启动模式是"standard",那么目标activity本身也会被移除栈,系统会创建新的实例; 这是因为对于"standard"模式的activity,系统总是会创建新的实例。

3.4. Affinity

Affinity用来标识activity启动后所归属的task,一个应用中的activity默认都归属同一个task即以应用包名命名的task; 可以在AndroidManifest.xml文件中使用taskAffinity属性改变这种默认task,所以同一个应用中的activity可以属于不同的task,而不同应用中的activity可以属于同一task。
taskAffinity接受string类型的值,不过这个string不能和activity的默认包名相同。

Affinity在下面两种情况下会起作用:
1. 用来启动activity的intent中包含FLAG_ACTIVITY_NEW_TASK
默认情况下,被启动的activity会被放进启动它的activity所属的task中。但是如果intent中含有FLAG_ACTIVITY_NEW_TASK,那么系统会寻找一个不同的task来存放新启动的activity,通常会是一个新的task, 但是如果已经有一个和被启动activity的affinity属性相同的task存在,那么新的activity会被放进这个task中,否则系统会创建一个新的task。

2. Actiivty的allowTaskReparenting属性被设置为了"true"
在这种情况下,如果activityaffinity指定的task切换到了前台运行,那么被启动的activity可以从被启动时所属的task切换到affinity所指定的task。


4. Clearing the back stack

如果用户长时间离开了一个task,那么系统会将栈中root activity之外的activity都清理掉,当用户重新回到task后,只有root activity可以恢复; 因为系统认为用户长时间离开再进入task,很可能不再继续之前的操作,而是有新的操作。但是也可以通过一些配置来改变这种默认行为。

  • alwaysRetainTaskState
    如果将task中root activity的"alwaysRetainTaskState"属性设置为”true“, 那么即使用户长时间离开task,系统就不会清理栈中的activity。

  • clearTaskOnLaunch
    如果将task中root activity的"clearTaskOnLaunch"属性设置为"true",那么每次用户离开task后再进入task,系统都会将root activity清理出栈,无论用户离开时间长短。

  • finishOnTaskLaunch
    这个属性和"clearTaskOnLaunch"类似,不过这个属性只针对一个activity,而不是整个task。它也可以导致一个activity被清理出栈,甚至root activity。如果被设置为"true",那么当用户离开task再返回后,之前的内容将不复存在。

启动一个新的task时,要注意一点,如果用户离开这个task后是否还能回去?所以针对"singleTask"和"singleInstance"启动模式的activity,最好要配置 “ACTION_MAIN” 和" CATEGORY_LAUNCHER" filter属性,让它显示在launcher中。


结束!
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值