跳到主要内容

Activity 基础

Activity 是 Android 四大组件中最常用的一个,它代表一个具有用户界面的单一屏幕。理解 Activity 的生命周期和使用方式是 Android 开发的基础。

什么是 Activity?

Activity 可以理解为应用的一个"页面"或"屏幕"。一个应用通常由多个 Activity 组成,每个 Activity 负责展示特定的界面和处理用户的交互。例如,一个邮件应用可能有:

  • 邮件列表 Activity:显示收件箱
  • 邮件详情 Activity:显示邮件内容
  • 写邮件 Activity:编辑新邮件

虽然现代 Android 开发推荐使用单 Activity 架构(配合 Fragment 和 Jetpack Compose),但理解 Activity 仍然是必要的。

创建 Activity

1. 创建 Activity 类

在 Android Studio 中,右键点击包名 → New → Activity → Empty Views Activity,会自动生成 Activity 类和对应的布局文件。

手动创建的步骤如下:

package com.example.myapp

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// 初始化界面和逻辑
}
}

代码说明:

  • 继承 AppCompatActivity 而不是 Activity,这样可以获得更好的兼容性和 Material Design 支持
  • onCreate() 是 Activity 创建时调用的方法
  • setContentView() 设置 Activity 的布局文件

2. 创建布局文件

res/layout/ 目录下创建 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, Android!"
android:textSize="24sp" />

<Button
android:id="@+id/btn_click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击我"
android:layout_marginTop="16dp" />

</LinearLayout>

3. 在清单文件中注册

所有 Activity 都必须在 AndroidManifest.xml 中注册:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.MyApp">

<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>

</manifest>

关键属性说明:

  • android:name:Activity 的类名,. 开头表示相对于包名
  • android:exported:是否允许其他应用启动此 Activity
  • <intent-filter>:定义 Activity 可以响应的 Intent
    • MAIN + LAUNCHER:表示这是应用的启动 Activity

Activity 生命周期

理解生命周期是正确使用 Activity 的关键。Activity 在其生命周期中会经历多个状态转换。

生命周期回调方法

class MainActivity : AppCompatActivity() {

private val TAG = "MainActivity"

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(TAG, "onCreate: Activity 创建")
}

override fun onStart() {
super.onStart()
Log.d(TAG, "onStart: Activity 即将可见")
}

override fun onResume() {
super.onResume()
Log.d(TAG, "onResume: Activity 获得焦点,可交互")
}

override fun onPause() {
super.onPause()
Log.d(TAG, "onPause: Activity 失去焦点")
}

override fun onStop() {
super.onStop()
Log.d(TAG, "onStop: Activity 不再可见")
}

override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy: Activity 即将销毁")
}

override fun onRestart() {
super.onRestart()
Log.d(TAG, "onRestart: Activity 重新启动")
}
}

生命周期状态图

三个嵌套循环

Activity 的生命周期可以分为三个嵌套循环:

1. 完整生命周期(Entire Lifetime)

onCreate()onDestroy()。在这个期间,Activity 完成创建到销毁的全部过程。

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 初始化资源、绑定数据
}

override fun onDestroy() {
// 释放资源
super.onDestroy()
}

2. 可见生命周期(Visible Lifetime)

onStart()onStop()。在这个期间,Activity 对用户可见(可能无法交互)。

override fun onStart() {
super.onStart()
// 注册广播接收器、开始动画
}

override fun onStop() {
// 注销广播接收器、停止动画
super.onStop()
}

3. 前台生命周期(Foreground Lifetime)

onResume()onPause()。在这个期间, Activity 处于前台,用户可以与之交互。

override fun onResume() {
super.onResume()
// 恢复暂停的操作、获取独占资源
}

override fun onPause() {
// 暂停操作、释放独占资源
super.onPause()
}

常见场景的生命周期变化

场景生命周期调用顺序
启动应用onCreate → onStart → onResume
按下返回键onPause → onStop → onDestroy
按下 Home 键onPause → onStop
从后台返回onRestart → onStart → onResume
打开新 ActivityonPause → onStop
关闭新 Activity 返回onRestart → onStart → onResume
旋转屏幕onPause → onStop → onDestroy → onCreate → onStart → onResume

Activity 之间的跳转

使用 Intent 启动 Activity

Intent 是 Android 中用于组件间通信的消息对象。使用 Intent 可以启动其他 Activity、发送广播、启动服务等。

// 在当前 Activity 中启动新 Activity
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)

传递数据

发送数据:

val intent = Intent(this, SecondActivity::class.java).apply {
putExtra("username", "张三")
putExtra("age", 25)
putExtra("is_member", true)
}
startActivity(intent)

接收数据:

class SecondActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)

// 获取传递的数据
val username = intent.getStringExtra("username") ?: ""
val age = intent.getIntExtra("age", 0)
val isMember = intent.getBooleanExtra("is_member", false)

Log.d("SecondActivity", "用户: $username, 年龄: $age, 会员: $isMember")
}
}

传递复杂数据

对于复杂对象,需要实现 SerializableParcelable 接口:

// 使用 Parcelable(推荐,性能更好)
@Parcelize
data class User(
val id: Int,
val name: String,
val email: String
) : Parcelable

// 发送
val user = User(1, "张三", "[email protected]")
val intent = Intent(this, SecondActivity::class.java).apply {
putExtra("user", user)
}
startActivity(intent)

// 接收
val user = intent.getParcelableExtra<User>("user")

获取返回结果

当需要从目标 Activity 返回结果时,使用 startActivityForResult(已废弃)或新的 Activity Result API:

// 定义协定
val startForResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == RESULT_OK) {
val data = result.data?.getStringExtra("result")
Log.d("MainActivity", "返回结果: $data")
}
}

// 启动 Activity
val intent = Intent(this, SecondActivity::class.java)
startForResult.launch(intent)

在 SecondActivity 中返回结果:

// 设置返回结果
val resultIntent = Intent().apply {
putExtra("result", "操作成功")
}
setResult(RESULT_OK, resultIntent)
finish() // 关闭当前 Activity

Activity 的启动模式

Activity 的启动模式决定了 Activity 在任务栈中的行为。在 AndroidManifest.xml 中通过 android:launchMode 属性设置。

四种启动模式

1. standard(默认)

每次启动都创建新实例,放入任务栈顶部。

<activity
android:name=".MainActivity"
android:launchMode="standard" />
启动顺序: A → B → B → A
任务栈: [A, B, B, A]

2. singleTop

如果要启动的 Activity 已在栈顶,则复用该实例,调用 onNewIntent();否则创建新实例。

<activity
android:name=".MainActivity"
android:launchMode="singleTop" />
当前栈: [A, B, C]
启动 C: [A, B, C](复用栈顶 C,调用 onNewIntent)
启动 B: [A, B, C, B](创建新 B)

3. singleTask

在系统中只存在一个实例。如果已存在,则将其上方的所有 Activity 出栈,并调用 onNewIntent()

<activity
android:name=".MainActivity"
android:launchMode="singleTask" />
当前栈: [A, B, C, D]
启动 B: [A, B](C、D 被出栈,B 调用 onNewIntent)

4. singleInstance

独占一个任务栈,系统中只有一个实例。其他应用也可以共享这个实例。

<activity
android:name=".MainActivity"
android:launchMode="singleInstance" />

处理 onNewIntent

对于 singleTop、singleTask、singleInstance 模式,需要处理 onNewIntent

override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
// 更新 Intent,处理新的启动参数
setIntent(intent)

val newData = intent.getStringExtra("new_data")
Log.d("MainActivity", "收到新数据: $newData")
}

Activity 状态保存与恢复

当系统因内存不足或配置变更(如屏幕旋转)销毁 Activity 时,需要保存和恢复状态。

保存状态

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)

// 保存需要恢复的数据
outState.putString("username", username)
outState.putInt("score", score)
}

恢复状态

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// 恢复保存的数据
if (savedInstanceState != null) {
username = savedInstanceState.getString("username", "")
score = savedInstanceState.getInt("score", 0)
}
}

// 或者使用 onRestoreInstanceState(在 onStart 之后调用)
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)

username = savedInstanceState.getString("username", "")
score = savedInstanceState.getInt("score", 0)
}

使用 ViewModel(推荐)

对于复杂的状态管理,推荐使用 ViewModel:

class MainViewModel : ViewModel() {
private val _username = MutableLiveData<String>()
val username: LiveData<String> = _username

private val _score = MutableLiveData<Int>()
val score: LiveData<Int> = _score

fun setUsername(name: String) {
_username.value = name
}

fun setScore(value: Int) {
_score.value = value
}
}

class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// ViewModel 中的数据在配置变更时自动保留
viewModel.username.observe(this) { name ->
// 更新 UI
}
}
}

Activity 的常见任务

设置标题栏

// 设置标题
supportActionBar?.title = "我的页面"

// 隐藏标题栏
supportActionBar?.hide()

// 启用返回按钮
supportActionBar?.setDisplayHomeAsUpEnabled(true)

// 处理返回按钮点击
override fun onSupportNavigateUp(): Boolean {
onBackPressedDispatcher.onBackPressed()
return true
}

全屏模式

// 隐藏状态栏和导航栏
window.decorView.systemUiVisibility = (
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
)

// 使用 WindowInsetsController(API 30+)
window.insetsController?.hide(WindowInsets.Type.statusBars())

设置横竖屏

// 代码中设置
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE // 横屏
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT // 竖屏

// 或在清单文件中设置
<activity
android:name=".MainActivity"
android:screenOrientation="portrait" />

小结

本章介绍了 Activity 的核心概念:

  1. Activity 基础:创建 Activity、注册清单、设置布局
  2. 生命周期:理解七个回调方法和三种嵌套循环
  3. Activity 跳转:使用 Intent 启动和传递数据
  4. 启动模式:standard、singleTop、singleTask、singleInstance
  5. 状态保存:onSaveInstanceState 和 ViewModel

下一章将学习 Android 的布局系统,掌握如何构建美观的用户界面。