当你还在用 Gson 时,Square那帮人已经开发出了 Moshi 了!!

Java进阶 专栏收录该内容
9 篇文章 0 订阅

原文地址

好久不见,曾经我们相处得很好,但是是时候说再见了。

在你的朋友圈中也许会听到这样的语句(也可能没有),但这并非是本篇文章的主题,我们要谈论的是一个新的关于 Android 和 kotlin 序列化框架!我们需要将 Gson 迁移到 Moshi上面了。

当我们谈论为啥Moshi是更优秀的框架,或者怎么迁移到 Moshi之前,我们先来了解一下今天的 Gson 的发展。

Gson,what?

当我们查看 Gson 的github仓库时,它是这么描述的:

一个Java 的序列化/反序列化框架,用来将Java对象转换成Json对象,或者反之。

那么它有以下缺点:

  • 很显然它对kotlin并不友好,当然也不是kotlin写的( Gson 是纯Java实现的),所以每个人都可以清楚的意识到 Gson 已经不再是一个现代的开发框架了。它发布于2008年,距离今天已经12年了,看上去已经不更新了(这个的确,看了一下最新的一次更新时间是9个月钱了),完完全全是一个将死的项目了。
  • 最近没有更新,上一次更新看上去并没有大的更新或者问题修复(意思就是小修小补),事实上不去碰那些运行得很好的程序,破坏数百万使用Gson库的app 是有道理的(个人认为这里还是正面夸赞了Gson的流行和稳定),但是对于Gson这个项目来说,它似乎正在死去。
  • Gson 库的方法数大概为1036个,大概是 Moshi 库中方法数的两倍(Moshi中方法数大概为500)。
  • 库的体积 使用 Gson 大约使你的app增大了300kb,而Moshi大概有120kb。
  • Gson 使用了 Java的反射实现了序列化和反序列,而 Moshi 使用了 Kotlin 代码自动支持。
  • Gson不支持对象属性有默认值。如果在Gson字符串中缺少了属性对应的字符串,即使你设置了默认值,它将来还是null值(这个不是特别明白啥意思)。

假设我们认为 Gson 将死,那我们将走向何方?当然我们可以继续使用 Gson,因为它一直都正常工作!但是对于那些好奇心很强的开发者和kotlin爱好者来说,我们还有 Moshi。接下来我们来看看 什么是 Moshi 和 为什么是 Moshi了。

什么是 Moshi ?

一个 现代的 kotlin 和 Java Json解析库

Moshi的 github地址 (也是大名鼎鼎的square公司出品的)。主要特点是 现代的、kotlin友好的、更快的、拥有大量可靠的功能。先来看看这些牛叉的功能吧:

更好的 API

Moshi提供了更好更现代的 API,你可以使用此强大功能的 API 进行简单整洁的操作。

在 Moshi中 注解(Annotation) 被视为最重要的部分,注解可以允许你添加一些信息来更加细粒度的实现上下文序列化。

  • 你可以自定义注解来解析你的Json数据属性,(就像解析颜色使用@ColorInt, @FromHexColor一样)
  • 自定义适配器或者上下文反序列可以使功能更加整洁,从而减少样板代码。
  • Moshi 拥有更好的、更具人性化的获取序列化失败信息的能力。在当你的app发布之后,从奇怪的堆栈信息中不知道应该做什么,那么Moshi将会是一个巨大的进步(可以帮助你获取异常信息)。
  • Moshi 拥有 newBuilder() 方法从上游的Adapter中来帮助创建新的Adapter,这就有点像OkHttp 或者 Okio builder模式了,它超级有用,因为你可以创建独立的Adapter,这样就不需要拥有解析全部对象的Adapter(这句话的意思,需要理解Moshi解析字符流的方式和Gson不一致,Gson是从前到后,一个字符不落下去解析,而Moshi可以直接跳过目标字符,只需要得到自己想要的字符)
  • Moshi 支持多态数据类型,同时也支持未知的数据类型的回退。
  • Moshi在 Kotlin 中拥有代码自动生成功能,这个很好!在注解的帮助下,你可以更加快速的序列化\反序列化.这个比Gson使用反射方法快多了。

Moshi 的表现

Moshi 比 Gson 要快(通过实验得出结论 [链接]), 而且Moshi消耗的内存更少,这是因为它使用了 Okio,Okio可以在解析Json字符流的过程提前预测或者期望忽略掉未知的、不需要的字段(从而达到速度快、内存小的目的,这里有篇文章讲得很清楚 ). Retrofit底层也是用了 Okio,所以你才会发生什么? Json序列化库(Moshi) 和 网络请求工具(Retrofit) 可以共用它们的缓冲区,这样将会在网络请求和序列化时降低内存的消耗。

理论说的差不多了,看看代码咋写吧

来看看咋样一步一步从Gson迁移到 Moshi 吧。

1. 添加 build.gradle 依赖
/*Moshi*/
def moshiVersion = "1.10.0"

implementation("com.squareup.moshi:moshi:$moshiVersion")

kapt("com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion")

implementation("com.squareup.retrofit2:converter-moshi:2.9.0")

2. 将所有的 @SerializedName 替换成 @Json
data class MediaCandidateData(
    @SerializedName("width")
    val width: Int,

    @SerializedName("height")
    val height: Int,

    @SerializedName("url")
    val url: String
)

替换为:


data class MediaCandidateData(
    @Json(name = "width")
    val width: Int,

    @Json(name = "height")
    val height: Int,

    @Json(name = "url")
    val url: String
)

3. 给所有的Data Class 添加 @JsonClass(generateAdapter = true) 注解

给所有的Data Class 添加 @JsonClass(generateAdapter = true)注解,将会参与到序列化\反序列化的进程中。它帮助Moshi使用代码自动生成而非使用将会降低速度的反射。

@JsonClass(generateAdapter = true)
data class MediaCandidateData(
    @Json(name = "width")
    val width: Int,

    @Json(name = "height")
    val height: Int,

    @Json(name = "url")
    val url: String
)

4. 替换Gson的实例为 Moshi

如果使用 Dagger 来提供依赖,你可以需要这么干:

@Singleton
@Provides
fun provideGson() = GsonBuilder().setLenient().create()

替换为:

@Singleton
@Provides
fun providesMoshi() = Moshi.Builder().build()
5. 使用 Retrofit时替换 converter

当你使用Retrofit 和 Dagger 时,你可能需要这么做:

@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient, gson: Gson) = Retrofit.Builder()
  .client(okHttpClient)
  .addConverterFactory(GsonConverterFactory.create(gson))
  .baseUrl(BASE_ENDPOINT)
  .build()

现在替换为:

@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient, mosh: Moshi) = Retrofit.Builder()
  .client(okHttpClient)
  .addConverterFactory(MoshiConverterFactory.create(mosh))
  .baseUrl(BASE_ENDPOINT)
  .build()

就是这么简单,从Gson迁移到 Moshi非常简单。
当然也有些特例需要单独讲明,这可能需要下篇文章说明了。

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值