核心方法:Intent
Intent 是 Android 中不同组件(如 Activity, Service, BroadcastReceiver)之间进行通信的“信使”,在启动 Activity 时,我们通过 Intent 来携带数据。

Intent 有两种主要用法:
- 显式 Intent:明确指定要启动的组件(类名),通常用于应用内部跳转。
- 隐式 Intent:只指定要执行的操作(如查看地图、拨打电话),而不指定具体组件,通常用于调用系统或其他应用的功能。
传递参数主要使用显式 Intent。
传递基本数据类型
这是最简单、最常用的方式,适用于 String, int, boolean, double, float, char, long, byte 等基本数据类型及其包装类。
从第一个 Activity (MainActivity) 发送数据
// MainActivity.kt
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btnSendData = findViewById<Button>(R.id.btn_send_data)
btnSendData.setOnClickListener {
// 1. 创建一个 Intent
val intent = Intent(this, SecondActivity::class.java)
// 2. 使用 putExtra() 方法添加数据
// 第一个参数是 "键" (Key),用于在接收方识别数据
// 第二个参数是 "值" (Value),要传递的数据
intent.putExtra("user_name", "张三")
intent.putExtra("user_age", 25)
intent.putExtra("is_logged_in", true)
// 3. 启动 SecondActivity
startActivity(intent)
}
}
}
在第二个 Activity (SecondActivity) 接收数据
// SecondActivity.kt
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
val tvReceivedData = findViewById<TextView>(R.id.tv_received_data)
// 1. 从 getIntent() 获取启动当前 Activity 的 Intent 对象
val intent = intent
// 2. 使用 getXXXExtra() 方法,根据之前设置的 "键" 来获取 "值"
// 注意:必须提供与 putExtra 时相同的键
// 为了防止 Intent 为 null 或键不存在,可以提供默认值
val userName = intent.getStringExtra("user_name") ?: "未知用户"
val userAge = intent.getIntExtra("user_age", 0) // 默认值 0
val isLoggedIn = intent.getBooleanExtra("is_logged_in", false) // 默认值 false
// 3. 将数据显示在界面上
val displayText = "欢迎, $userName!\n你的年龄是: $userAge\n登录状态: $isLoggedIn"
tvReceivedData.text = displayText
}
}
传递复杂数据类型(如对象)
当你需要传递一个自定义的对象时,不能直接使用 putExtra,Android 提供了两种主要方法来实现:Parcelable 和 Serializable。

使用 Parcelable (推荐)
Parcelable 的性能比 Serializable 更好,因为它通过将对象数据写入一个 Parcel 对象来实现序列化,这个过程比 Serializable 的基于 I/O 的序列化要快。
步骤:
- 让你的数据类实现
Parcelable接口。 - 实现
describeContents()和writeToParcel()方法。 - 创建一个
Parcelable.Creator静态成员,用于反序列化。
示例数据类 User.kt
import android.os.Parcel
import android.os.Parcelable
// 实现 Parcelable 接口
data class User(val name: String, val age: Int) : Parcelable {
// 描述内容接口,几乎所有情况都返回 0
override fun describeContents(): Int {
return 0
}
// 将对象数据写入 Parcel
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeString(name)
dest.writeInt(age)
}
// CREATOR 是必须的,用于从 Parcel 中重建对象
// 使用了 Kotlin 的 `object` 关键字创建一个单例
companion object CREATOR : Parcelable.Creator<User> {
// 从 Parcel 创建对象数组
override fun createFromParcel(source: Parcel): User {
return User(source.readString()!!, source.readInt())
}
// 创建一个指定大小的对象数组
override fun newArray(size: Int): Array<User?> {
return arrayOfNulls(size)
}
}
}
发送和接收
// 在 MainActivity.kt 中发送
val user = User("李四", 30)
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("user_object", user) // 直接 putExtra 即可
startActivity(intent)
// 在 SecondActivity.kt 中接收
val receivedUser = intent.getParcelableExtra<User>("user_object")
if (receivedUser != null) {
// 使用 receivedUser.name 和 receivedUser.age
Log.d("SecondActivity", "Received User: ${receivedUser.name}, ${receivedUser.age}")
}
Kotlin 便利方案:@Parcelize
为了手动实现 Parcelable 的繁琐代码,Kotlin Android Extensions 提供了一个注解 @Parcelize,可以让你用一行代码搞定所有事情。
import android.os.Parcelize import kotlinx.parcelize.Parcelize // 只需添加 @Parcelize 注解 @Parcelize data class User(val name: String, val age: Int) : Parcelable // 之后的使用方式完全不变,代码会自动生成
使用 Serializable
Serializable 是 Java 提供的序列化接口,非常简单,只需要让你的类实现 Serializable 接口即可,无需编写额外代码,但性能较差,不推荐在性能敏感的场景下使用。
示例数据类 User.kt
import java.io.Serializable;
// 只需实现 Serializable 接口
public class User implements Serializable {
private String name;
private int age;
// 构造函数、Getter 和 Setter
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
在 Kotlin 中:
// 只需实现 Serializable 接口 data class User(val name: String, val age: Int) : Serializable
发送和接收
发送和接收的方式与 Parcelable 完全一样,只是类实现接口不同。
// 发送
val user = User("王五", 40)
intent.putExtra("user_object", user)
// 接收
val receivedUser = intent.getSerializableExtra("user_object") as User?
使用 Bundle
Bundle 是一个键值对的数据容器,本质上 Intent 内部也使用 Bundle 来存储数据,你可以先把所有数据放进一个 Bundle,再把整个 Bundle 放进 Intent。
这在需要传递大量数据或者想把数据打包管理时很有用。
// 发送方
val intent = Intent(this, SecondActivity::class.java)
val bundle = Bundle()
bundle.putString("title", "我的标题")
bundle.putInt("code", 200)
intent.putExtra("my_data_bundle", bundle)
startActivity(intent)
// 接收方
val bundle = intent.getBundleExtra("my_data_bundle")
if (bundle != null) {
val title = bundle.getString("title")
val code = bundle.getInt("code")
// ...
}
使用 Activity 的 ViewModel
如果你需要在同一个屏幕内的多个 Fragment 之间,或者 Activity 和其 Fragment 之间共享数据,ViewModel 是最佳选择,它也可以用于 Activity 间传递数据,但通常不推荐用于完全独立的 Activity 间跳转,因为 ViewModel 的生命周期与 Activity 的实例绑定。
适用场景:当两个 Activity 有紧密关系,比如一个 Activity 是另一个的配置界面,返回后需要刷新数据。
优点:
- 数据在屏幕旋转等配置更改后不会丢失。
- 自动管理生命周期,内存泄漏风险低。
简单示例:
// 1. 创建一个共享的 ViewModel
// 在第一个 Activity 中
val sharedViewModel: SharedViewModel by viewModels()
sharedViewModel.setData("这是从 MainActivity 传递的数据")
// 跳转到第二个 Activity
startActivity(Intent(this, SecondActivity::class.java))
// 2. 在第二个 Activity 中获取
val sharedViewModel: SharedViewModel by viewModels()
val data = sharedViewModel.getData()
// 使用 data...
ViewModel 的具体实现和生命周期管理是另一个大话题,但它是现代 Android 开发中数据共享的核心组件。
使用 Application 类
你可以将数据存储在自定义的 Application 类的单例实例中,这样,任何 Activity 或 Service 都可以访问到这些数据。
适用场景:全局共享数据,比如用户登录信息、应用主题设置等。
步骤:
- 创建一个继承自
Application的类。 - 在
AndroidManifest.xml中声明这个类。 - 通过
context.applicationContext获取实例并读写数据。
示例 MyApplication.kt
import android.app.Application
class MyApplication : Application() {
// 使用 lateinit 延迟初始化
lateinit var currentUser: User
override fun onCreate() {
super.onCreate()
// 初始化数据
currentUser = User("默认用户", 0)
}
}
在 AndroidManifest.xml 中注册
<application
android:name=".MyApplication" <!-- 指定你的 Application 类 -->
...>
...
</application>
在 Activity 中使用
// 在任何 Activity 中
val myApp = application as MyApplication
myApp.currentUser = User("全局用户", 99)
val name = myApp.currentUser.name
注意:Application 是一个全局单例,要小心使用,避免存储过多数据或导致内存泄漏。
总结与最佳实践
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 基本数据类型 | 传递少量简单数据(如 ID, 标题, 状态) | 简单、直接、高效 | 无法传递复杂对象 |
Parcelable |
传递自定义对象(推荐) | 性能高,是 Android 的标准做法 | 实现稍显繁琐(但 @Parcelize 解决了) |
Serializable |
传递自定义对象 | 实现极其简单,只需实现接口 | 性能差,基于反射,开销大 |
Bundle |
管理和传递大量或分组的数据 | 数据结构化,方便管理 | 本质是 Intent 内部的实现,多了一层封装 |
ViewModel |
同个任务(Task)内的 Activity/Fragment 通信 | 生命周期感知,数据不随配置改变丢失 | 不适合完全独立的 Activity 间跳转 |
Application |
全局共享数据 | 任何地方都可访问,生命周期与应用相同 | 容易被滥用,导致内存问题,破坏组件化 |
最佳实践建议:
- 优先使用
putExtra传递基本数据类型:这是最直接、最高效的方式。 - 传递对象时,首选
Parcelable+@Parcelize:这是 Android 官方推荐的性能最优方案。 - 只在组件间有紧密生命周期关联时使用
ViewModel:Activity 和其内部的多个 Fragment。 - 谨慎使用
Application类:仅用于存储真正的全局状态,避免用它来临时传递数据,以免造成代码耦合和内存问题。 - 避免使用
Serializable传递大对象或频繁传递的数据:除非你追求代码的极致简洁,并且不关心性能损失。
