我有關於使用GSON和其他東西的幾個音符。
- 你應該關閉我在
finally
塊/ O資源,以確保你沒有資源泄漏(available
和read
可能拋出,防止資源被close
d除外)。 (我也不敢肯定,如果使用available
這裏是一個不錯的主意。)
- 你只是沒有在這種情況下使用
String
秒。字符串通常是這種情況下的性能/記憶殺手(很大程度上取決於它們的結果大小),因爲字符串會累積到內存中,因此您將首先將它們全部收集到內存中,從而失去了您的即時創意。在最壞的情況下,它可以通過OutOfMemoryError
完成您的申請。
- 您可以使用指定的編碼讀取輸入流,因此不需要字符串緩衝。
JsonParser
旨在返回JSON樹:JsonElement
包含整個 JSON樹在內存中。聽起來類似於上面的琴絃情況,對嗎?這裏的另一個表現處罰
- 創建
Gson
情況下可能有些昂貴(取決於如何比較,當然),你可以實例化一次:這是線程安全的。
JsonStreamParser
也不是一個選項,因爲每個next()
都會在內存中生成另一個JSON樹分支(同樣取決於您的JSON文檔及其元素的大小)。
Gson.fromJson
使用查找,以找到最佳類型的適配器,你問一個Gson
實例的類型的適配器一次,然後不浪費時間查找了。類型適配器通常也是完全線程安全的,因此可以被緩存。
綜上所述,你可以按如下方式實現:
private static final Gson gson = new Gson();
private static final TypeAdapter<MyEntity> myEntityTypeAdapter = gson.getAdapter(MyEntity.class);
private static void loadJsonInDb(final String path)
throws IOException {
// Java 7 language features can be easily converted to Java 6 try/finally
// Note the way how you can decorate (wrap) everything: an input stream (byte streams) to a reader (character streams, UTF-8 here) to a JSON reader (more high-level character reader)
try (final JsonReader jsonReader = new JsonReader(new InputStreamReader(context.getAssets().open(path), "UTF-8"))) {
// Ensure that we're about to open the root object
jsonReader.beginObject();
// And iterate each object property
while (jsonReader.hasNext()) {
// And check it's name
final String name = jsonReader.nextName();
// Another Java 7 language feature
switch (name) {
// Is it datas?
case "datas":
// The consume it's opening array token
jsonReader.beginArray();
// And iterate each array element
while (jsonReader.hasNext()) {
// Read the current value as an MyEntity instance
final MyEntity myEntity = myEntityTypeAdapter.read(jsonReader);
// Now do what you want here
}
// "Close" the array
jsonReader.endArray();
break;
default:
// If it's something other than "datas" -- just skip the entire value -- Gson will do it efficiently (I hope, not sure)
jsonReader.skipValue();
break;
}
}
// "Close" the object
jsonReader.endObject();
}
}
簡單的講,你只需要編寫一個解析器消耗每個令牌。現在,具有下列JSON文檔:
{
"object": {
},
"number": 2,
"array": [
],
"datas": [
{
"k": "v1"
},
{
"k": "v2"
},
{
"k": "v3"
}
]
}
解析器上述將提取$.datas.*
僅消耗較少的資源成爲可能。代// Now do what you want here
與System.out.println(myEntity.k);
會產生:
V1
V2
V3
假設MyEntity
是final class MyEntity{final String k=null;}
。請注意,您也可以使用這種方法處理無限的JSON文檔。
數據庫插入可能是瓶頸。你使用內容提供者還是直接插入?你使用beginTransaction()endTRansaction()嗎? –
Indead DB插入是瓶頸之一,實際上我測量的是處理時間。對於JSON解析:17秒,對於數據庫插入:50秒。這就是爲什麼我想在解析期間在數據庫中插入數據到數據庫中,這將是一種並行處理(解析+數據庫插入)。我不使用beginTransaction或endTRansaction,它會提高性能嗎? – Mouss
我有類似的問題。約1000條記錄的Json數組。如果使用內容提供者插入時間〜1分鐘。如果直接訪問db(無內容提供者)並插入單個事務需要大約10秒。 –