使用Intent传递对象|青训营笔记

135 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第13天

使用Intent传递对象

  • Intent的用法相信你已经比较熟悉了,我们可以借助它来启动Activity、启动Service、发送广播等。
  • 在进行上述操作的时候,我们还可以在Intent中添加一些附加数据,以达到传值的效 果,比如在FirstActivity中添加如下代码:
val intent = Intent(this, SecondActivity::class.java) 
intent.putExtra("string_data", "hello") 
intent.putExtra("int_data", 100) 
startActivity(intent)

这里调用了Intent的putExtra()方法来添加要传递的数据,之后在SecondActivity中就可 以得到这些值了,代码如下所示:

intent.getStringExtra("string_data") 
intent.getIntExtra("int_data", 0) 

然而,putExtra()方法中所支持的数据类型是有限的,虽然常用的一些 数据类型是支持的,但是当你想去传递一些自定义对象的时候,就会发现无从下手。所以接下来我来讲讲用Intent来传递对象的技巧。
14.2.1 Serializable方式
使用Intent来传递对象通常有两种实现方式:Serializable和Parcelable。

  • Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象 可以在网络上进行传输,也可以存储到本地。至于序列化的方法非常简单,只需要让一个类去 实现Serializable这个接口就可以了。 比如说有一个Person类,其中包含了name和age这两个字段,如果想要将它序列化,就可以这 样写:
class Person : Serializable { 
 var name = "" 
 var age = 0 
} 

这里我们让Person类实现了Serializable接口,这样所有的Person对象都是可序列化的 了。 然后在FirstActivity中只需要这样写:

val person = Person() 
person.name = "Tom" 
person.age = 20 
val intent = Intent(this, SecondActivity::class.java) 
intent.putExtra("person_data", person) 
startActivity(intent) 

可以看到,这里我们创建了一个Person的实例,并将它直接传入了Intent的putExtra()方法 中。
由于Person类实现了Serializable接口,所以才可以这样写。

接下来在SecondActivity中获取这个对象也很简单,写法如下:

val person = intent.getSerializableExtra("person_data") as Person 

Parcelable
除了Serializable之外,使用Parcelable也可以实现相同的效果,不过不同于将对象进行序列 化,Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是 Intent所支持的数据类型,这样就能实现传递对象的功能了。 下面我们来看一下Parcelable的实现方式,修改Person中的代码,如下所示:

class Person : Parcelable { 
 var name = "" 
 var age = 0 
 
 override fun writeToParcel(parcel: Parcel, flags: Int) { 
 parcel.writeString(name) // 写出name 
 parcel.writeInt(age) // 写出age 
 } 
 
 override fun describeContents(): Int { 
 return 0 
 } 
 
 companion object CREATOR : Parcelable.Creator<Person> { 
 override fun createFromParcel(parcel: Parcel): Person { 
 val person = Person() 
 person.name = parcel.readString() ?: "" // 读取name 
 person.age = parcel.readInt() // 读取age 
 return person 
 } 
 
 override fun newArray(size: Int): Array<Person?> { 
 return arrayOfNulls(size) 
 } 
 } 
} 

Parcelable的实现方式要稍微复杂一些。
可以看到,首先我们让Person类实现了Parcelable 接口,这样就必须重写describeContents()和writeToParcel()这两个方法。其中 describeContents()方法直接返回0就可以了,而在writeToParcel()方法中,我们需要 调用Parcel的writeXxx()方法,将Person类中的字段一一写出。注意,字符串型数据就调用 writeString()方法,整型数据就调用writeInt()方法,以此类推。