这是我参与「第四届青训营 」笔记创作活动的第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()方法,以此类推。