最近想继续自己之前的梦想,入了安卓编程的坑项目问题等做完了慢慢复盘,先总结今天遇到的难题。如何在Activity中传递数据。对于简单的数据而言可以直接通过putExtra来进行数据传送
val data = "Hello SecondActivity"
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("extra_data", data)
startActivity(intent)
但是对于复杂的数据结构而言 putExtra方法就不存在重构方法了,需要自己完成。通过查阅资料发现大家都在采用Parcelable的管道符来进行数据传输的。每个Activity相当于独立的存在,本身的数据通信只能在内存中另外开辟一段空间让Intet类携带数据跑到另一个Activity中。如何使用Parcelable管道方法呢。目前我的数据结构是这样的
class Fridge(val name: String? ="", val location:String?="", val time:String?="")
class SearchJson(val response:Int, var data: List<Fridge>)
本身SearchJson是用来接收json返回的数据用的,这里本身数据主要是后面的data部分所以就全部传递了。直接使用putExtra是无法传递的。本身没有重载这个方法,尝试使用ArrayList结构也不行,拷贝时会直接闪退。虽然说是继承关系,但是还是不能直接拷贝。所以就采用Parcelable方法传递,这个方法相当于把整个结构进行了流式排列,将整个结构按照一定顺序压入队列然后进行线性发送,所以把这个类作为父类,然后就需要重载五个函数
constructor(parcel: Parcel) :this
override fun writeToParcel(p0: Parcel?, p1: Int)
override fun describeContents(): Int
companion object CREATOR : Parcelable.Creator<SearchJson> {
override fun createFromParcel(parcel: Parcel): SearchJson {
return SearchJson(parcel)
}
override fun newArray(size: Int): Array<SearchJson?> {
return arrayOfNulls(size)
}
这五个方法主要功能是前两个分别是反序列化和序列化。简单来说就是打包函数和解压函数如果只是简单元素,IDE会帮你自动补全的,基本不用操心,但是有列表就需要自己写一下,这里我也是初上手试图解决一下这几个问题
parcel提供了序列化(writexxx)和反序列化(readxxx)来进行操作。一般的如writeint就可以把int型写入。如果涉及到list型也可以直接使用writelist 不过这里主意,对于list是其他类的列表,其他类也需要继承Parcelable类写相应的序列化和反序列化函数来帮助打包。
override fun writeToParcel(p0: Parcel?, p1: Int) {
p0?.writeInt(response)
if(data.isNotEmpty())
{
p0?.writeInt(data.size)
p0?.writeList(data)
}
else
{
p0?.writeInt(0)
}
这边是我写的打包函数,对于data而言本身是List
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(name)
parcel.writeString(location)
parcel.writeString(time)
}
这样打包部分就结束了
接下来是 反序列化部分。当进入后进行解包先贴代码
constructor(parcel: Parcel) : this(response=parcel.readInt(),data= ArrayList<Fridge>()) {
if(parcel.readInt()>0)
{
parcel.readList(data,Fridge.javaClass.classLoader)
}
}
我这里主要是加了个校验如果不加校验也是可以的。在this指针部分先对类的变量进行初始化。然后再赋值,如果是基础类型如response可以直接赋值 parcel.readInt() 对于复杂类型先初始化ArrayList 注意ArrayList是可变数组,不存在list的初始化操作。下面使用的是readList函数,如果write部分使用writearraylist这里就也要一致。两边不一致会导致解析出错。readlist的两个参数分别是要写入的变量,和list内部的类型。注意第二个参数是 Fridge.javaClass.classLoader
第三部分是外部代码这部分就简单了
val intent = Intent(this@SearchActivity,SearchResultActivity::class.java)
intent.putExtra("fridge_list",list)
startActivity(intent)
这部分跟一般的没什么不一样 有个小细节 java语言的this指针是类。写作searchActivity.this` kotlin写作 `this@SearchActivity
val receive= intent.getParcelableExtra<SearchJson>("fridge_list")
val list= receive?.data
这部分使用Parcelable函数来进行解析注意类型名称。
PS:现学现卖还是有点难度的
参考
https://stackoverflow.com/questions/6300608/how-to-pass-a-parcelable-object-that-contains-a-list-of-objects
https://developer.android.com/reference/android/os/Parcel#readList(java.util.List,%20java.lang.ClassLoader)
https://medium.com/the-lazy-coders-journal/easy-parcelable-in-kotlin-the-lazy-coders-way-9683122f4c00
| 区别 | Serializable | Parcelable |
|---|---|---|
| 所属API不同 | 属于Java API | 属于 Android SDK |
| 原理不同 | Serializable 序列化和反序列化需要大量的I/O操作 | Parcleable序列化和反序列化不需要大量的I/O操作 |
| 开销不同 | 开销大 | 开销小 |
| 效率不同 | 效率低 | 效率高 |
| 使用场景不同 | Serializable序列化到本地或者网络传输 | Parcleable是内存序列化 |

Comments NOTHING