一. 简介

应用程序的每一个界面都是一个Activity,所以也有人称其为视图界面。从字面的意思去理解,Activity具有活动的意思,我们在应用中进行的操作都是集中在Activity上面完成,例如拨号、拍照、发送email、看地图。每一个activity被给设置到一个窗口,在上面可以绘制交互界面。 一个应用程序通常由多个activities组成,他们通常是松耦合关系,通常一个应用程序包含有一个主Activity,即点击桌面图标的时候首先进入的Activity。

继承关系

1
2
3
4
5
6
7
8
9
java.lang.Object
↳ android.content.Context
↳ android.content.ContextWrapper
↳ android.view.ContextThemeWrapper
↳ android.app.Activity
↳ androidx.core.app.ComponentActivity
↳ androidx.activity.ComponentActivity
↳ androidx.fragment.app.FragmentActivity
↳ androidx.appcompat.app.AppCompatActivity

二. Acticity的创建与启动

1. 创建Activity

① 创建的步骤

第一步是创建一个类继承于AppCompatActivity(它是Acticity的子类,主要是为了兼容低版本的一些问题)。

第二步是在 AndroidManifest.xml 中注册你的 Activity,正常情况下使用四大组件 (Activity,Service,BrocastReceiver,ContentProvider) 都需要注册。

注意:使用AndroidStudio,有简便的创建Activity的方法,如下图所示:

② 系统的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}

//注册的信息
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

AndroidStudio 在新的项目创建完成后,会自动创建一个Activity并注册。从上面的代码我们可以知道,默认创建的 MainActivity 强制重写了 onCreate 方法,在 onCreate 中,通过 setContentView 为 Activity 设置我们自定义的页面布局文件。

注册信息表明这个Activity是主Activity,在Android系统点击应用图标首先会进入该Activity。

2. 启动Activity

参考:Intent

① 显示启动

显式Intent通过直接设置需要调用的Activity类,可以唯一确定一个Activity,意图特别明确,所以是显式的。

1
2
Intent intent = new Intent(this, SecondActivity.class);  
startActivity(intent);

② 隐式启动

隐式,不明确指定启动哪个Activity,而是设置Action、Data、Category,让系统来筛选出合适的Activity。筛选是根据所有的intent-filter来筛选。

以 Action 为例子,创建一个Activity,在AndroidManifest.xml对应的里面的intent-filter添加 action,一般命名方式是包名+Action名,category设置为android.intent.category.DEFAULT

1
2
3
4
5
6
7
8
9
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="android.intent.action.SECOND" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>

Intent intent = new Intent("android.intent.action.SECOND");
startActivity(intent);

③ 默认启动

通过桌面图标点击应用图标进入程序的第一个Activity,因其启动方式有别上述两个方式,将其划分为第三类的启动方式。 若Activity在AndroidManifest.xml文件的intent-filter的action和category,如下:

1
2
3
4
5
6
7
<activity android:name="Activity的名字">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

那么,点击桌面的应用图标即可启动Activity。

三. Activity的生命周期

1. onCreate

这是第一个执行的方法,在Activity的生命周期中只执行一次。在这个方法中做一些初始化工作,比如调用setContentView去加载界面布局,初始化Activity所需要的数据等。

2. onStart

这是第二个执行的方法,表示Activity正在启动。这个时候Activity是可见的,但是还没有出现在前台,不能和用户进行交互。这个时候可以理解为Activity已经显示出来,但是我们还看不到。

3. onResum

这是紧接着 onStart 方法 的方法,表示Activity可见,并且已经出现在前台并开始活动,能和用户正常进行交互。需要注意的是onStart和onResume的区别,二者都是Activity可见,但是onStart时Activity还在后台,而onResume时Activity到了前台了,这时候可以开启动画或者获取独占性设备的操作如打开相机、获取麦克风等。

4. onPause

表示Activity由前台转到后台,正常情况下,紧接着onStop就会被调用,这时仍然可见。(如果这时候快速地回到当前Activity,那么onResume会被调用,这类情况属于极端情况,用户操作很难重现这一场景。)此时可以做一些存储数据,停止动画等操作,但是注意不能太耗时,如果太耗时会影响到新的Activity的显示。onPause是先执行完,新的Activity的onCreate才会执行。

5. onStop

表示Activity即将停止,当前的Activity对用户不在可见。可稍微做些重量级的回收操作。

6. onRestart

表示Activity正在重新启动,一般情况下,当前的Activity从不可见的状态变为可见状态时,onRestart就会被调用。这种情形一般是用户操作出现所致,比如用户按Home键回到桌面或者用户打开了一个新的Activity,这时候Activity就会暂停,接着用户又回到该Activity。后续调用onStart()。

7. onDestory

表示Activity正在被销毁,是生命周期的最后一个回调,也是只调用一次。发生的条件是Activity本身已经执行完毕,或者系统资源不足需要回收资源将Activity销毁。

四. Activity生命周期使用的常见例子

1. 打开程序的Activity

onCreate -> onStart -> onResume

2. 回到Home或者后台

onPause -> onStop

3. 后台打开

onRestart -> onStart -> onResume

4. 关闭程序的Activity

onPause -> onStop -> onDestory

5. 从FirstActivity 到 SecondActivity

First.onCreate -> First.onStart -> First.onResume -> 点击按钮,开启一个新的Activity -> First.onPause -> Second.onCreate -> Second.onStart -> Second.onResume -> First.onStop

6. 补充

我们考虑如下几类情况: 1、当一个Toast弹出的时候,会发生回调么? No 2、当一个AlertDialog弹出的时候,会发生回调么? No, 如果AlertDialog获取焦点,Activity会触发onWindowFocusChanged回调 3、当一个PopWindow弹出的时候,会发生回调么? No, 如果PopWindow获取焦点,如mPopupWindow.setFocusable(true),Activity会触发onWindowFocusChanged回调。 4.横竖屏切换时,会造成Activity被销毁然后重新创建。若在Activity配置android:configChanges=“orientation”,横竖屏切换时,只触发onConfigurationChanged( )回调,Activity不会被重新创建。

五. Activity的启动模式

1. 简介

Activity 有四种启动模式,决定 Activity 对象的创模和复用策略。

2. 启动模式原理

首先需要明确 “任务栈” 是什么?

Android 任务栈又称为 Task,它是一个栈类型的数据结构:先进后出。它用于存储我们的 Activity 组件。

每次打开一个新的 Activity 或 退出一个 Activity 都会在任务栈的结构中添加或减少一个 Activity,一个任务栈包含了一个 Activity 集合。Android 系统可以通过 Task 有序的管理每个 Activity ,并决定那个 Activity 与用户进行交互:只用在栈顶的 Activity 才可以跟用户进行交互。

在应用程序退出时,必须把所有任务栈中的 Activity 清除栈时,任务栈才会被销毁。当然任务栈可以移动到后台,并且保存每个 Activity 的状态。可以有序的给用户列出Activity的任务,同时也不会丢失 Activity 的信息。

应用程序中可能不止一个任务栈,某些情况下,单独的一个 Activity 可以独享一个任务栈,也会存在一个任务栈的 Activity 可以来自不同的 App,同一个 App 中的 Activity 可能在不同的任务栈当中。

1
2
3
4
5
6
7
8
//获取ActivityMananger
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
//获取任务栈 可能是多个
List<ActivityManager.RunningTaskInfo> runningTasks = am.getRunningTasks(5);
//获取当前的任务栈
ActivityManager.RunningTaskInfo runningTaskInfo = runningTasks.get(0);
//获取当前任务栈中 Activity 个数,即当前没有换存活的 Activity 实例个数。
int numRunning = runningTaskInfo.numRunning;

3. 为什么需要启动模式

在应用程序开发过程中,一般都需要在多个 Activity 组件之间跳转,也可能需要在本应用中打开其他应用的可复用的 Activity。在开发过程中需要跳转到原来已经开启的 Activity 实例,此时我们希望这个 Activity 可以被重用而不是再重新创建一个新的 Activity 实例,但根据 Android 系统的默认行为,每次都会为我们创建一个新的 Activity 实例对象并添加到任务栈中,而且 Activity 的数据和信息状态都将会被保留 。

4. 四种任务栈的特点

① Standard 模式(一般模式)

系统默认模式,每次启动一个Activity都会重新创建一个新的实例,而不管Activity是否已经创建了一个实例。

② SingTop 模式(栈顶复用模式)

栈顶复用模式,系统启动时,系统会判断当前栈顶Activity是不是要启动的Activity,如果是则不需要创建新的Activity而直接引用这个Activity,如果不是那么创建新的Activity。系统会回调Activity的onNewIntent()的方法。

③ SingTask 模式(栈内复用模式)

栈内复用模式,如果栈内已经存在了一个Activity的实例,那么Activity不会被重新创建,同时这个Activity的onNewIntent()方法会被回调,并将该Activity实例置于栈顶,原先处于该实例顶部的Activity实例会被出栈销毁。如果是其他程序启动Activity,那么它会重新创建一个任务栈。

④ SingleInstance 模式(单一实例模式)

单实例模式,是singleTask的加强版,具有singleTask所有特点,并且此种模式下Activity只有一个实例,并且只能单独的存在一个任务栈中。

5. 使用方式

① Xml方式

在 AndroidManifes.xml 中 ,找到声明 Activity 的位置,在 Actvity XML 属性 android:launchMode=“standard”,其他模式(singleTop,singleTask,singleInstance) 声明。

② 代码设置

利用 Intent 指定 Flag 标志位来使用启动模式。

1
2
3
Intent intent = new Intent(this, SecondActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//Flag
startActivity(intent);

setFlags方法说明:

1
2
3
4
5
6
7
8
9
10
//使用这种方式启动Activity,当Activity启动其他Activity的时候,该Activity会被销毁,不入栈。 
Intent.FLAG_ACTIVITY_NO_HISTORY
//使用一个新的Task来启动Activity,但每个Activity都将在一个新的Task中
Intent.FLAG_ACTIVITY_NEW_TASK
//使用singleTop模式来启动一个Activity
Intent.FLAG_ACTIVITY_SINGLE_TOP
//使用singleTask模式来启动一个Activity
Intent.FLAG_ACTIVITY_CLEAR_TOP
...
//SingleInstances 只能在 AndroidManifest.xml 中声明。

6. 应用场景

LaunchMode 例子
standard 邮件,mainfest没有配置
singleTop 登录页面,推送通知栏
singleTask 程序模块逻辑入口主页面,WebView页面,扫一扫页面
singleInstance 系统Launcher,来电显示等系统应用

参考文章

Android 四大组件之Activity

Activity 使用详解

继承Activity和AppCompatActivity区别

Android中从一个Activity跳转到另一个Activity所经历的生命周期…..

onStart()和onResume()/onPause()和onStop()的区别?