Kotlin序列化

  • Kotlin 下 Parcelable Serializable 使用

  • 资料来源:

    <>

  • 更新

    1
    20.05.05

导语

  • 最近在重构 Nowakelock 的 ipc 部分,整理一下相关内容.
  • 首选肯定是 Parcelable ,无奈 hook 部分都在 frame 层,Parcelable 暂时无解.

序列化

  • 序列化和反序列化其实就是方便传输对象.
  • 这里是需要在几个系统 Service 里通过 Bundle 传递数据.
  • Parcelable 全部都在内存,效率高,需要实现部分多,使用繁琐.(在 kotlin 不成立)
  • Serializable 实现简单,但是是基于反射实现的,故有性能损失,但是是最通用的.

Parcelable

  • 直接实现 Parcelable 确实略微繁琐.但是这是 kotlin 啊.

  • Android stuio 的 kotlin 插件,只需要在数据类添加 @Parcelize 即可.

  • 启用 androidExtensions,在应用的 build.gradle 中添加.

    1
    2
    3
    4
    androidExtensions {
    // features = ["parcelize"] //仅使用 @Parcelize
    experimental = true
    }
  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Parcelize
    data class Test2(
    val name: String?,
    var packageName: String? = "",
    var count: Int = 0,
    var blockCount: Int = 0,
    var countTime: Long = 0,
    var blockCountTime: Long = 0
    ) : Parcelable
  • 使用生成插件我们可以看到手写情况下,我们需要写多少代码.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    data class Test2(
    val name: String?,
    var packageName: String? = "",
    var count: Int = 0,
    var blockCount: Int = 0,
    var countTime: Long = 0,
    var blockCountTime: Long = 0
    ) : Parcelable {
    constructor(source: Parcel) : this(
    source.readString(),
    source.readString(),
    source.readInt(),
    source.readInt(),
    source.readLong(),
    source.readLong()
    )

    override fun describeContents() = 0

    override fun writeToParcel(dest: Parcel, flags: Int) = with(dest) {
    writeString(name)
    writeString(packageName)
    writeInt(count)
    writeInt(blockCount)
    writeLong(countTime)
    writeLong(blockCountTime)
    }

    companion object {
    @JvmField
    val CREATOR: Parcelable.Creator<Test2> = object : Parcelable.Creator<Test2> {
    override fun createFromParcel(source: Parcel): Test2 = Test2(source)
    override fun newArray(size: Int): Array<Test2?> = arrayOfNulls(size)
    }
    }
    }

Serializable

  • 其他不多表了,直接是示例.

    1
    2
    3
    4
    5
    6
    7
    8
    data class Test(
    val name: String?,
    var packageName: String? = "",
    var count: Int = 0,
    var blockCount: Int = 0,
    var countTime: Long = 0,
    var blockCountTime: Long = 0
    ) : Serializable
  • 实现确实简单..

使用

  • 这里是配合 ContentProvider 的 call 方法,就不贴全部代码了.

  • 放入 Bundle

    1
    2
    3
    4
    val extras = Bundle()
    extras.putSerializable("Test",Test("test1","package1",2,2,2,2))
    extras.putParcelable("Test2", Test2("test1","package1",2,2,2,2))
    val bundle = context.contentResolver.call(url, method, null, extras)
  • 获取也类似..不再表述了.

Parcelable 坑

  • 相同的代码在 Android Test 中可以通过但是在 Hook 中就是不行.

  • 一直提示 android.os.BadParcelableException: ClassNotFoundException when unmarshalling:

  • 搜集过资料表示懵逼..class loader 不知道该怎么序列化.

  • 一种解释是: class loader 分为两类,一类是 framework classloader 可以加载 Android 的 class,另一个是 apk classloader 继承自 framework classloader ,既可以加载 android 的 class,也能加载应用的 class.但是 hook 的全是系统服务…

  • 另一种是注入的系统 Service 中没有定义好的 Parcelable 类.xposed 应该可以注入成员变量,待续…