目录
1.活动组件Activity
Activity 是 Android 四大组件之一,它是用户交互的入口点,代表了一个具有用户界面的单一屏幕。
1.1Activity的生命周期
在每次新建活动页面时,可以看到在Java代码中生成了方法onCreate,该方法用于活动创建的一些相关操作,包括加载xml布局、设置一些视图的文本或者注册视图的监听器等。onCreate方法的一系列动作是一个活动最开始的行为即该方法最先调用。除了onCreate方法外还有一些关于活动页面生命周期的方法。下面列举主要的方法。
onCreate:创建活动,此时系统会将该页面布局加载进内存中,页面进入初始状态。
onStart:开启活动,此时系统会将活动页面显示在屏幕上,页面进入就绪状态。
onResume:恢复活动,此时活动页面能够与用户正常交互,页面进入活跃状态。
onPause:暂停活动,此时无法与用户交互,页面进入就绪状态。
onStop:停止活动,此时活动页面不在页面上显示,页面进入初始状态。
onDestroy:销毁活动,此时系统收回活动页面占据的系统资源,把页面从内存中清除。
onRestart:重启活动,处于停止状态的活动无需再次经历onCreate的重复创建过程,而是由onRestart到onStart的重启过程。
onNewIntent:重启已有的活动实例,由onNewIntent到onResume,页面进入活跃状态。
下图为活动状态变化图。

下面为代码示例,新建两个页面,在两个页面之间跳转(跳转之后有讲)查看页面生命周期。
//两个页面的布局文件除按钮不同其余一样
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ActivityLifeCycle.FirstLifeCycleActivity"
android:orientation="vertical">
<Button
android:id="@+id/button_next"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="点击跳转至下一个页面" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="生命周期:\n" />
</LinearLayout>
两个Java代码不同之处在于按钮监听器的逻辑处理,其余大差不差。
public class FirstLifeCycleActivity extends AppCompatActivity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first_life_cycle);
Button button_next = findViewById(R.id.button_next);
Calendar calendar = Calendar.getInstance();
textView = findViewById(R.id.textView);
textView.setText(textView.getText().toString() + String.format("%s:%s:%s onCreate\n", calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND)));
button_next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//跳转至下一页
startActivity(new Intent(FirstLifeCycleActivity.this, SecondLifeCycleActivity.class));
}
});
}
@Override
protected void onStart() {
super.onStart();
Calendar calendar = Calendar.getInstance();
textView.setText(textView.getText().toString() + String.format("%s:%s:%s onStart\n", calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND)));
}
@Override
protected void onStop() {
super.onStop();
Calendar calendar = Calendar.getInstance();
textView.setText(textView.getText().toString() + String.format("%s:%s:%s onStop\n", calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND)));
}
@Override
protected void onDestroy() {
super.onDestroy();
Calendar calendar = Calendar.getInstance();
textView.setText(textView.getText().toString() + String.format("%s:%s:%s onDeatroy\n", calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND)));
}
@Override
protected void onPause() {
super.onPause();
Calendar calendar = Calendar.getInstance();
textView.setText(textView.getText().toString() + String.format("%s:%s:%s onPause\n", calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND)));
}
@Override
protected void onResume() {
super.onResume();
Calendar calendar = Calendar.getInstance();
textView.setText(textView.getText().toString() + String.format("%s:%s:%s onResume\n", calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND)));
}
@Override
protected void onRestart() {
super.onRestart();
Calendar calendar = Calendar.getInstance();
textView.setText(textView.getText().toString() + String.format("%s:%s:%s onRestart\n", calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND)));
}
}
//第二个页面设置按钮监听器代码
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//结束当前页面即可自动返回上一页
finish();
}
});
效果图如下,第一张为进入第一个页面,第二张为跳转至第二个页面,第三张为返回第一个页面。可以大致看出页面的生命周期。



1.2Activity的启动模式
上面讲过两个页面之间的跳转,那么为什么从第二个页面返回时是回到第一个页面而不是返回桌面呢?这是因为系统给每一个正在运行的APP分配了活动栈,栈内容纳着已经创建但还未被销毁的页面信息。而栈是一种先进后出、后进先出的数据结构,所以当启动第一个页面时它入栈且在栈顶,当跳转至第二个页面时它在第一个页面后面且在栈顶。当销毁第二个页面时它出栈此时的栈顶为第一个页面,所以会返回到第一个页面而不是桌面。如下图所示。

上面的出入栈的情况只是默认的标准模式,实际上Android可以在创建活动时指定启动模式,通过启动模式控制活动的出入栈行为。APP有两种设置方式,一种是在AndroidManifest.xml中添加修改Activity的属性android:launchMode,该属性表示本活动该以哪种模式启动;另一种是在Java代码中设置,通过调用Intent对象的setFlags方法,表明后续打开的活动页面采用哪种模式启动。
launchMode 属性值总览
| 启动模式 | XML 值 | 描述 | 新实例创建 | 任务栈行为 |
|---|---|---|---|---|
| standard | "standard" | 默认模式,每次启动创建新实例 | 总是创建 | 放入调用者所在任务栈 |
| singleTop | "singleTop" | 栈顶复用模式 | 不在栈顶时创建 | 同 standard,但栈顶时复用 |
| singleTask | "singleTask" | 栈内单例模式 | 不存在时创建 | 创建新任务栈或使用现有栈 |
| singleInstance | "singleInstance" | 全局单例模式 | 不存在时创建 | 单独任务栈,仅容纳该 Activity |
| 启动标志 | 主要功能 | 典型场景 |
|---|---|---|
FLAG_ACTIVITY_NEW_TASK | 在新任务栈中启动Activity。 如果该Activity已存在于某个后台任务栈中,则整个任务栈会被切换到前台。 | 从非Activity上下文(如Service、Application)启动Activity时必须使用;特定场景下与singleTask模式行为类似。 |
FLAG_ACTIVITY_SINGLE_TOP | 如果要启动的Activity已位于任务栈栈顶,则不会创建新实例,而是调用其onNewIntent()方法。 | 避免栈顶Activity重复创建,例如处理搜索页面或通知点击。 |
FLAG_ACTIVITY_CLEAR_TOP | 如果要启动的Activity已在当前任务栈中,则会销毁位于它之上的所有其他Activity,使其位于栈顶。 | 用于“回到首页并重新开始”之类的场景。 如果目标Activity的启动模式是标准模式(standard),它本身也会被销毁并重建。此时可配合FLAG_ACTIVITY_SINGLE_TOP使用以避免重建。 |
FLAG_ACTIVITY_CLEAR_TASK | 跳转到新Activity时,会先清空当前任务栈中所有已有的Activity。 | 通常与FLAG_ACTIVITY_NEW_TASK组合使用,用于应用启动后展示全新的界面,如闪屏页后进入主界面。 |
FLAG_ACTIVITY_NO_HISTORY | 通过此标志启动的Activity,在跳转到其他Activity后,该Activity会自动销毁,不会保留在任务栈中。 | 适用于一次性的中间页面,例如引导页或过渡页。 |
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | 使用此标识位启动的Activity所在的任务栈,不会出现在“最近应用”列表(即Android的多任务视图)中。 | 适用于一些不希望用户通过“最近应用”直接返回的隐私或安全相关页面。 |
FLAG_ACTIVITY_REORDER_TO_FRONT | 如果要启动的Activity已经在当前任务栈中,则将它提到栈顶,而不是创建新实例。 | 当应用存在多个入口或复杂导航时,用于将后台的某个Activity激活到前台,例如从设置页快速返回主界面而不重复创建。 |
AndroidManifest.xml中的部分代码。
//添加了launchMode属性,其值为standard即默认值。
<activity
android:name=".ActivityLifeCycle.FirstLifeCycleActivity"
android:exported="true"
android:launchMode="standard">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Java中部分代码示例,修该第一个页面中按钮监听器的逻辑代码。setFlags中的两个值代表着跳转到新Activity时,会先清空当前任务栈中所有已有的Activity并开辟新的活动栈。第一个页面跳转至第二个页面后点击按钮发现并没有与之前一样返回第一个页面而是返回到桌面。这就是setFlags方法的具体用途,在AndroidManifest.xml中已经设置启动模式但在运行时却是按照Java代码中设置的值运行,可见Java代码设置的值的优先级要高于在AndroidManifest.xml中设置的启动模式的值,如果需要设置多个flag可以用按位或(|)操作符组合起来使用。
button_next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//跳转至下一页
Intent intent = new Intent(FirstLifeCycleActivity.this,SecondLifeCycleActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});

被折叠的 条评论
为什么被折叠?



