文章目录
一、Activity 生命周期
Activity 是安卓应用中最常用、最重要的应用组件。
一个 Activity 可以有下面四种状态:
- 运行状态:Activity 位于前台,用户可见,可以获得焦点。
- 暂停状态:其它 Activity 位于前台,用户可见,但无法获得焦点。
- 停止状态:Activity 不可见,失去焦点。
- 销毁状态:该 Activity 结束,或 Activity 所在的进程被结束。
一个 Activity 的生命周期图如下所示:
- onCreate():创建 Activity 时被调用,只会被调用一次。
- onStart():启动 Activity 时被回调。此方法调用之后,该 Activity 已处于用户可见的状态,只是该页面无法获得焦点,无法与用户进行交互。
- onResume():此方法回调后 Activity 处于用户可见,可以与用户交互的状态。
- onPause():暂停 Activity 时被回调。此方法调用之后,该 Activity 已处于用户可见的状态,只是该页面无法获得焦点,无法与用户进行交互。
- onStop():停止 Activity 时调用。此方法调用后 Activity 变成完全不可见状态。
- onRestart():重新启动 Activity 时被回调,使之进入前台。
- onDestroy():销毁 Activity 时调用,该方法只会被调用一次。
二、配置 Activity
安卓要求所有的应用程序组件(Activity、Service、ContentProvider、BroadcastReceiver)都必须进行显示配置。在 AndroidManifest.xml 文件中为 <application…/> 元素添加 <activity…/> 子元素即可配置 Activity。一般需要制定以下几个属性:
- name:指定该 Activity 的实现类的类名。
- icon:指定该 Activity 对应的图标。
- label:指定该 Activity 的标签。
- exported:指定该 Activity 是否允许被其他应用调用。如果将该属性设置为 true,那么该 Activity 将可以被其他应用调用。
- launchMode:指定该 Activity 的加载模式,该属性支持 standard、singleTop、singleTask 和 singleInstance 四种加载模式。
在 AndroidManifest.xml 文件中 <application…/> 元素下配置 Activity 的例子如下:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!-- 配置了三个 activity -->
<activity android:name=".FizzBuzzTest"></activity>
<activity android:name=".ColorTest" />
<!-- 指定该 activity 为应用程序的入口 -->
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
三、Activity的 4 种加载模式及使用场景
安卓采用 Task 来管理多个 Activity,当我们启动一个应用时,安卓就会为其创建一个 Task。Task 以栈的形式来管理 Activity:先启动的 Activity 放在 Task 栈底,后启动的 Activity 放在 Task 栈顶。Activity 的加载模式就负责管理实例化、加载 Activity 的方式,并可以控制 Activity 与 Task 之间的加载关系。
3.1 standard 模式
每次通过 standard 模式启动目标 Activity 时,总会为目标 Activity 创建一个新的实例,并将该 Activity 添加到当前 Task 栈中——这种模式不会启动新的 Task,新 Activity 将被添加到原有的 Task 中。
使用场景
- 普通页面一般使用此种模式
3.2 singleTop 模式
singleTop 模式与 standard 模式基本相似,不同的地方在于:当想要启动的目标 Activity 已经位于 Task 栈顶时,系统不会重新创建目标 Activity 的实例,而是直接复用已有的 Activity 实例。如果将要启动的目标 Activity 没有位于 Task 栈顶,此时行为模式与 standard 模式完全相同。
使用场景:
- 一般点击通知之后跳转的界面会使用此模式(避免当前已经在通知跳转的界面时点击通知后重复创建该页面)
- 在跳转一些有启动延迟的界面时(一般是由于网络或者动画造成的,例如登录后跳转,可能由于网络延迟导致跳转延迟,这时候用户可能多次点击跳转按钮)
3.3 singleTask 模式
采用 singleTask 这种加载模式的 Activity 能保证在同一个 Task 内只有一个实例,当系统采用 singleTask 模式启动目标 Activity 时,可分为如下三种情况:
- 如果将要启动的目标 Activity 不存在,系统将会创建目标 Activity 的实例,并将它加入 Task 栈顶。
- 如果将要启动的目标 Activity 已经位于 Task 栈顶,此时与 singleTop 模式的行为相同。
- 如果将要启动的目标 Activity 已经存在、但没有位于 Task 栈顶,系统会把位于该 Activity 上面的所有 Activity 移出 Task 栈,从而使得目标 Activity 转入栈顶。
使用场景:
- 一般使用在 App 主页,例如浏览器的主页,当我们回到浏览器主页后,点击返回键就应该退出应用了
3.4 singleInstance 模式
在 singleInstance 加载模式下,系统无论从哪个 Task 中启动目标 Activity,只会创建一个目标 Activity 实例,并会使用一个全新的 Task 栈来加载该 Activity 实例。当系统采用 singleInstance 模式启动目标 Activity 时,可分为如下两种情况:
- 如果将要启动的目标 Activity 不存在,系统会先创建一个全新的 Task,再创建目标 Activity 的实例,并将它加入新的 Task 栈顶。
- 如果将要启动的目标 Activity 已经存在,无论它位于哪个应用程序中、位于哪个 Task 中,系统都会把该 Activity 所在的 Task 转到前台,从而使该 Activity 显示出来。
采用 singleInstance 模式加载的 Activity 总是位于栈顶,且采用 singleInstance 模式加载的 Activity 所在的 Task 只包含该 Activity。
使用场景:
- 呼叫来电界面
四、启动和关闭 Activity
Activity 启动其它 Activity 有如下两种方法
4.1 startActivity(Intent intent)
直接启动其它 Activity
//创建需要启动的 Activity 对应的 Intent
var intent = Intent(this@MainActivity, SecondActivity::class.java)
//启动 intent 对应的 Activity
startActivity(intent)
4.2 startActivityForResult(Intent intent, int requestCode)
启动其它 Activity 并返回结果,为了获取被启动的 Activity 所返回的结果,需要完成以下两个步骤:
- 当前 Activity 需要重写 onActivityResult(int requestCode, int resultCode, Intent intent),当被启动的 Activity 返回结果时,该方法将会被触发,其中 requestCode 代表请求码,标识该方法是由哪个请求的结果所触发的;而 resultCode 代表 Activity 返回的结果码,标识返回的数据来自哪个新的 Activity。
- 被启动的 Activity 需要调用 setResult() 方法设置处理结果。
第一个 Activity 的跳转相关的代码如下;
// 创建需要启动的 Activity 对应的 Intent
var intent = Intent(this@MainActivity, SecondActivity::class.java)
// 启动 intent 对应的 Activity,设置 requestCode 为0
startActivityForResult(intent, 0)
// 重写 onAvtivityResult() 方法,以回调的方式来获取指定 Activity 返回的结果
override fun onAvtivityResult(requestCode: Int, resultCode: Int, intent: Intent){
// 通过requestCode 和 resultCode 进行匹配
if (requestCode == 0 && resultCode == 2){
// 取出 intent 里面的数据
val num = intent.getIntExtra("num", 0)
// 将结果显示在控件中
result.setText(num.toString())
}
}
第二个 Activity 的跳转相关的代码如下:
button.setOnClickListener{
val intent = Intent()
val num = 3
intent.putExtra("num", num)
// 设置该 Activity 的结果码
setResult(2, intent)
// 结束该 Activity
finish()
}