常见的 intent 的传递数据的方式

Serializable / Parcelable 是“让对象可以被传递”的方式;
Bundle 是“装数据的盒子”;
CharSequence 是“一类文本数据的接口”。


1. Serializable:Java 自带的序列化方式

1.1 它是什么?

Serializable 是 Java 提供的接口,用来把对象转换成可以存储或传输的形式。

比如你有一个对象:

data class User(
    val name: String,
    val age: Int
)

正常情况下,这个对象不能直接放进 Intent 里传给另一个 Activity

如果你让它实现 Serializable

import java.io.Serializable

data class User(
    val name: String,
    val age: Int
) : Serializable

它就可以被传递了。


1.2 常见用法:Activity 之间传对象

发送数据

val user = User("张三", 18)

val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("user", user)
startActivity(intent)

接收数据

val user = intent.getSerializableExtra("user") as? User

Android 13 之后推荐这样写:

val user = intent.getSerializableExtra("user", User::class.java)

1.3 什么时候适合用 Serializable?

适合:

简单对象
数据量不大
不频繁传递
对性能要求不高

比如:

data class Book(
    val id: Int,
    val title: String
) : Serializable

1.4 Serializable 的特点

优点:

写起来简单
只要实现 Serializable 接口即可

缺点:

性能比 Parcelable 差
序列化过程使用反射,开销相对大
Android 中不如 Parcelable 高效

2. CharSequence:文本数据接口

2.1 它是什么?

CharSequence 不是专门用来序列化对象的,它是一个表示“字符序列”的接口。

常见的实现类有:

String
StringBuilder
SpannableString
Editable

所以:

val text: CharSequence = "你好"

是可以的,因为 String 实现了 CharSequence


2.2 String 和 CharSequence 有什么区别?

String 是具体的字符串类型。

CharSequence 是更大的范围。

String 是 CharSequence 的一种

比如:

fun setText(text: CharSequence) {
    textView.text = text
}

这样这个方法不仅能接收普通字符串:

setText("普通文本")

也能接收带样式的文本:

val spannable = SpannableString("红色文字")
setText(spannable)

2.3 常见用法:TextView 设置文本

Android 中很多文本相关 API 都使用 CharSequence

textView.text = "Hello"

实际 TextView.setText() 接收的就是:

setText(text: CharSequence)

因为它不仅要支持普通文本,还要支持富文本。


2.4 常见用法:传递文本

Intent 中也可以传递 CharSequence

val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("title", "标题内容")
startActivity(intent)

接收:

val title = intent.getCharSequenceExtra("title")

不过如果只是普通字符串,大多数时候直接用 String 更常见:

val title = intent.getStringExtra("title")

2.5 CharSequence 适合什么场景?

适合:

文本内容
TextView 显示
带样式的文本
Editable 输入框内容
Spannable 富文本

例如带颜色的文本:

val text = SpannableString("重要提示")
text.setSpan(
    ForegroundColorSpan(Color.RED),
    0,
    4,
    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)

textView.text = text

这里 SpannableString 就是 CharSequence 的一种。


3. Parcelable:Android 推荐的高效对象传递方式

3.1 它是什么?

Parcelable 是 Android 专门设计的一套序列化机制。

它的主要用途是:

在 Android 组件之间高效传递对象

比如:

Activity → Activity
Activity → Fragment
Service → Activity

3.2 和 Serializable 有什么区别?

简单对比:

对比项 Serializable Parcelable
来源 Java 标准 Android 专用
使用难度 简单 稍复杂
性能 较低 较高
适合场景 简单对象、低频传递 Android 组件间高频对象传递
是否推荐 可用 Android 中更推荐

一句话:

Serializable 写起来简单,Parcelable 性能更好。


3.3 Kotlin 中使用 Parcelable

以前写 Parcelable 比较麻烦,但 Kotlin 可以用 @Parcelize 简化。

首先在 build.gradle 中启用插件:

plugins {
    id("kotlin-parcelize")
}

然后写类:

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class User(
    val name: String,
    val age: Int
) : Parcelable

3.4 Activity 之间传 Parcelable

发送

val user = User("李四", 20)

val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("user", user)
startActivity(intent)

接收

Android 13 之前:

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

Android 13 之后推荐:

val user = intent.getParcelableExtra("user", User::class.java)

3.5 Fragment 传 Parcelable

创建 Fragment

val fragment = DetailFragment().apply {
    arguments = Bundle().apply {
        putParcelable("user", user)
    }
}

Fragment 中接收

val user = arguments?.getParcelable<User>("user")

Android 13 之后:

val user = arguments?.getParcelable("user", User::class.java)

3.6 Parcelable 适合什么场景?

适合:

Android 组件之间传递对象
对象字段比较多
传递比较频繁
希望性能更好

例如:

@Parcelize
data class Product(
    val id: Long,
    val name: String,
    val price: Double,
    val coverUrl: String
) : Parcelable

4. Bundle:Android 的数据包/数据盒子

4.1 它是什么?

Bundle 可以理解为一个 键值对容器

类似:

Map<String, Any>

它用来装各种数据:

String
Int
Boolean
Float
Parcelable
Serializable
StringArrayList
Bundle

4.2 Bundle 的典型用法

Activity 之间传数据

其实 Intent.putExtra() 底层就会把数据放进类似 Bundle 的结构里。

你可以直接用:

val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("name", "王五")
intent.putExtra("age", 22)
startActivity(intent)

接收:

val name = intent.getStringExtra("name")
val age = intent.getIntExtra("age", 0)

也可以自己创建 Bundle:

val bundle = Bundle().apply {
    putString("name", "王五")
    putInt("age", 22)
}

val intent = Intent(this, DetailActivity::class.java)
intent.putExtras(bundle)
startActivity(intent)

接收:

val bundle = intent.extras
val name = bundle?.getString("name")
val age = bundle?.getInt("age")

4.3 Fragment 传参数

这是 Bundle 最常见的场景之一。

推荐写法

class DetailFragment : Fragment() {

    companion object {
        fun newInstance(userId: Long): DetailFragment {
            return DetailFragment().apply {
                arguments = Bundle().apply {
                    putLong("user_id", userId)
                }
            }
        }
    }
}

接收:

class DetailFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val userId = arguments?.getLong("user_id") ?: 0L
    }
}

使用:

val fragment = DetailFragment.newInstance(1001L)

4.4 保存页面状态

Bundle 还经常用于保存 Activity 或 Fragment 的状态。

比如屏幕旋转时保存数据:

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

    outState.putString("input_text", editText.text.toString())
}

恢复:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val inputText = savedInstanceState?.getString("input_text")
}

4.5 Bundle 可以装 Parcelable

val bundle = Bundle().apply {
    putParcelable("user", user)
}

接收:

val user = bundle.getParcelable<User>("user")

4.6 Bundle 可以装 Serializable

val bundle = Bundle().apply {
    putSerializable("user", user)
}

接收:

val user = bundle.getSerializable("user") as? User

5. 它们之间的关系

可以这样理解:

Bundle 是盒子
Serializable 和 Parcelable 是让对象可以放进盒子的方式
CharSequence 是一种常见的文本数据类型

比如:

val bundle = Bundle()

bundle.putString("title", "标题")
bundle.putInt("age", 18)
bundle.putParcelable("user", user)
bundle.putSerializable("book", book)
bundle.putCharSequence("content", spannableText)

这里:

Bundle 负责装数据
Parcelable 负责让 user 可以被装进去
Serializable 负责让 book 可以被装进去
CharSequence 负责表示 content 这种文本

6. 常见选择建议

6.1 传普通字符串

String

intent.putExtra("title", "商品详情")

接收:

val title = intent.getStringExtra("title")

6.2 传普通数字、布尔值

直接用基本类型:

intent.putExtra("id", 1001L)
intent.putExtra("isVip", true)

接收:

val id = intent.getLongExtra("id", 0L)
val isVip = intent.getBooleanExtra("isVip", false)

6.3 传简单对象,不在意性能

可以用 Serializable

data class User(
    val name: String,
    val age: Int
) : Serializable
intent.putExtra("user", user)

6.4 传 Android 组件间对象,推荐用 Parcelable

推荐:

@Parcelize
data class User(
    val name: String,
    val age: Int
) : Parcelable
intent.putExtra("user", user)

6.5 Fragment 传参

推荐用 Bundle

val fragment = DetailFragment().apply {
    arguments = Bundle().apply {
        putLong("id", 1001L)
        putString("title", "详情页")
    }
}

6.6 保存临时状态

Bundle

override fun onSaveInstanceState(outState: Bundle) {
    outState.putString("keyword", searchEditText.text.toString())
}

7. 一个完整例子

假设要从 UserListActivity 跳转到 UserDetailActivity,传一个用户对象。

方式一:Parcelable 推荐

User 类

@Parcelize
data class User(
    val id: Long,
    val name: String,
    val age: Int
) : Parcelable

发送

val user = User(1L, "张三", 18)

val intent = Intent(this, UserDetailActivity::class.java).apply {
    putExtra("user", user)
}

startActivity(intent)

接收

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

textView.text = user?.name

方式二:Serializable 简单但性能差一点

User 类

data class User(
    val id: Long,
    val name: String,
    val age: Int
) : Serializable

发送

val intent = Intent(this, UserDetailActivity::class.java)
intent.putExtra("user", user)
startActivity(intent)

接收

val user = intent.getSerializableExtra("user") as? User

8. 最后总结

类型 作用 常见场景
Serializable Java 序列化对象 简单对象传递
Parcelable Android 高性能对象传递 Activity/Fragment 传对象
Bundle 键值对数据容器 Intent 参数、Fragment 参数、状态保存
CharSequence 文本数据接口 TextView、富文本、Spannable

最实用的记忆方式:

传字符串、数字:直接 putExtra
传对象:优先 Parcelable,简单场景可用 Serializable
Fragment 参数:用 Bundle
文本显示:CharSequence / String
富文本显示:SpannableString,它也是 CharSequence

如果只记一个原则:

Android 组件之间传复杂对象,优先用 Parcelable
传参容器用 Bundle
普通文本用 String,富文本用 CharSequence

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇