前言
android在序列化的时候有两种模式,一种是传统的Serializable,另一种就是android特有的Parcelable方式。另种序列化有各自的选择方式 实现Parcelable的作用 1)永久性保存对象,保存对象的字节序列到本地文件中; 2)通过序列化对象在网络中传递对象; 3)通过序列化在进程间传递对象。 选择序列化方法的原则 1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。 2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。 3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。
可以看到当我们不需要存储到磁盘时使用Parcelable这种序列化方式更加高效,但是有个问题,就是实现Parcelable需要编写大量的代码,尽管现在有一些ide插件可以帮你生成相应代码,但是一个bean类多出这么多代码也是蛮蛋疼的,而且看起来也较乱,所以我写了这个aop工具在编译成class文件时动态实现Parcelable
使用
在项目gradle文件里添加依赖
buildscript {
repositories {
....
maven{
url "https://dl.bintray.com/wuhaoxuan1225/maven/"
}
}
dependencies {
....
classpath 'com.skateboard.parcelablehelper:parcelablehelper:1.0.0'
....
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
在module的gradle文件里添加插件的引用
apply plugin: 'parcelablehelper'
在需要实现Parcelable接口的类上添加注解列化
import com.skateboard.parcelableannoation.Parcelable;
import com.skateboard.parcelableannoation.Ignore;
@Parcelable
public class Demo {
private String name;
}
原理
结合android gradle的Transform以及asm来实现该功能,编写gradle插件,利用android gradle的Transform获取编译后生成的class文件,然后利用asm动态修改相应的添加注释的文件。
核心代码
因为主要就是对Transfom的编译和ASM的编写,这里就不展开描述了,可以去看一看相关的文档,这里只是介绍一些基本的类的用途。
1递归生成class文件目录,并对标注了@Parcelable注解的类进行修改,生成相应代码
/**
* 获取目录下class文件并调用asm解析
* */
object ParcelableByteCodeUtil {
fun transformDirectoryInput(input: File, output: File) {
if (output.exists()) {
FileUtil.forceDelete(output)
}
FileUtil.forceMkdir(output)
val srcDirPath = input.absolutePath
val destDirPath = output.absolutePath
if (input.isDirectory) {
input.listFiles().forEach {
val destFilePath = it.absolutePath.replace(srcDirPath, destDirPath)
val destFile = File(destFilePath)
if (it.isDirectory) {
transformDirectoryInput(it, destFile)
} else if (it.isFile) {
FileUtils.touch(destFile)
performClassParse(it, destFile)
}
}
}
}
private fun performClassParse(inputFile: File, outputFile: File) {
if (inputFile.name.endsWith(".class") && inputFile.name != "R.class" && inputFile.name != "BuildConfig.class" && !inputFile.name.startsWith("R$")) {
ParcelableParser.parseClass(inputFile, outputFile)
} else {
FileUtil.writeToFile(inputFile, outputFile)
}
}
}
2.ParcelableCreatorGenerator
这个类利用ASM动态生成CREATOR的内部类,用来对应实现Parcelable接口需要的CREATOR变量
3.ParcelableGenerateVisitor
生成Parcelable相应的接口方法,为相应的属性字段生产相应的write和read调用。