一行註解幫你搞定Parcelable

前言

android在序列化的時候有兩種模式,一種是傳統的Serializable,另外一種就是android特有的Parcelable方式。另種序列化有各自的選擇方式 實現Parcelable的做用 1)永久性保存對象,保存對象的字節序列到本地文件中; 2)經過序列化對象在網絡中傳遞對象; 3)經過序列化在進程間傳遞對象。 選擇序列化方法的原則 1)在使用內存的時候,Parcelable比Serializable性能高,因此推薦使用Parcelable。 2)Serializable在序列化的時候會產生大量的臨時變量,從而引發頻繁的GC。 3)Parcelable不能使用在要將數據存儲在磁盤上的狀況,由於Parcelable不能很好的保證數據的持續性在外界有變化的狀況下。儘管Serializable效率低點,但此時仍是建議使用Serializable 。android

能夠看到當咱們不須要存儲到磁盤時使用Parcelable這種序列化方式更加高效,可是有個問題,就是實現Parcelable須要編寫大量的代碼,儘管如今有一些ide插件能夠幫你生成相應代碼,可是一個bean類多出這麼多代碼也是蠻蛋疼的,並且看起來也較亂,因此我寫了這個aop工具在編譯成class文件時動態實現Parcelablegit

使用

在項目gradle文件裏添加依賴github

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文件裏添加插件的引用bash

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動態修改相應的添加註釋的文件。app

核心代碼

由於主要就是對Transfom的編譯和ASM的編寫,這裏就不展開描述了,能夠去看一看相關的文檔,這裏只是介紹一些基本的類的用途。maven

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變量ide

3.ParcelableGenerateVisitor

生成Parcelable相應的接口方法,爲相應的屬性字段生產相應的write和read調用。工具

源碼

Github性能

相關文章
相關標籤/搜索