首页 > 解决方案 > 从 android 资产中解析微小的 JSON 非常慢

问题描述

我正在用 Kotlin 编写一个简单的 Android 应用程序,它将向用户显示按类别划分的祈祷。assets 文件夹中有 5 个 JSON 文件,每个文件只有大约 10 KiB。

我使用 Klaxon 将 JSON 文件解析为这两个数据类:

data class Prayer(val prayerName: String, val verseTitle: String, val verseBody: String,
              val prayerLine: String, val prayerBody: String, val prayerEnding: String)

data class PrayerCategory(val title: String, val bgImage: String, val headerImage: String,
                      val prayers : List<Prayer>)

这是我用于解析祈祷的代码:

private fun loadPrayerNames(jsonFile: String) {
    val millis = measureTimeMillis {
        val input = assets.open("${jsonFile}.json")
        val prayerCategory = Klaxon().parse<PrayerCategory>(input)

        if (prayerCategory != null) {
            for (prayer in prayerCategory.prayers) {
                val prayerName = prayer.prayerName
                prayersMap[prayerName] = prayer
            }
        }
    }

    println("Loading prayer category took $millis ms.")
}

如您所见,资产只有一种访问权限。没有 assets.list(),没有废话。正如你所注意到的,我已经测量了时间..让你猜猜..这是调试输出:

加载祈祷类别花费了 3427 毫秒。

是的,没错。加载和解析 10KiB 大 JSON 花了3.5 秒!我重复。不涉及火箭科学。只需解析 10 KiB JSON。3.5秒……嗯……

顺便说一句,我正在诺基亚 6.1 上测试它,这是一款非常活泼的手机。

所以..我的问题:

  1. 是什么导致了这种行为?
  2. 除了建立一个存储大约 50 个祈祷的数据库之外,还有什么方法可以加快速度?

我将非常感谢您的帮助!

标签: androidjsonkotlinklaxon

解决方案


在性能方面,Android 资产似乎名声不佳。但是,我的测试证明,在这种情况下,是 Klaxon 库负责。

在 Klaxon 中发现主要性能问题(请参阅https://github.com/cbeust/klaxon/issues/154)后仍未修复,我尝试了推荐的替代方案:Moshi(https://github.com/square/莫西)。

Moshi 确实提高了性能,但解​​析我的 JSON 仍然需要大约 1 秒。

在这些实验之后,我求助于使用 JSONObject 的老式解析:

data class Prayer(val prayerName: String, val verseTitle: String, val verseBody: String,
                val prayerLine: String, val prayerBody: String, val prayerEnding: String) {
    companion object {
        fun parseJson(json: JSONObject) : Prayer = Prayer(json.getString("prayerName"),
                json.getString("verseTitle"),  json.getString("verseBody"),
                json.getString("prayerLine"),  json.getString("prayerBody"),
                json.getString("prayerEnding"))

    }
}

data class PrayerCategory(val title: String, val bgImage: String, val headerImage: String,
                        val prayers : List<Prayer>) {
    companion object {
        fun parseJson(json: JSONObject): PrayerCategory {
            val prayers = ArrayList<Prayer>()
            val prayersArray = json.getJSONArray("prayers")

            for(i in 0 until prayersArray.length()) {
                prayers.add(Prayer.parseJson(prayersArray.getJSONObject(i)))
            }

            return PrayerCategory(json.getString("title"), json.getString("bgImage"),
                json.getString("headerImage"), prayers)
        }
    }
}

这将解析时间从 3427 毫秒减少到 13 毫秒。结案。;-)


推荐阅读