我想知道是否应该在我的应用程序中保留一个 Gson 对象的单例实例来解析 json。
这种方法有什么问题吗?是过早的优化吗?
最佳答案
我认为这两种变体都可以,但是如果您过于频繁地创建新的 Gson
实例,则效果不是很好,因为
- 您的应用程序消耗更多内存
- 创建新对象并不便宜
- 在不同地方使用自定义参数创建
Gson
实例时,您可能会遇到兼容性问题
与现在一样,Gson
实例是线程安全的,因此您可以通过单例模式或通过 DI(依赖注入(inject))获得 Gson
的单个实例。而且我认为创建几个 Gson
的实例具有意义,以防您使用不同的 API/API 版本,例如或者如果您必须以不同方式解析相同的响应。
已更新
但是,请注意,当您尝试在多线程应用程序中使用单个 Gson
实例时,有一些容易错过的陷阱。我将用一个例子来解释这一点。这只是一个例子,但你必须了解本质。
让我们想象一下您必须专门将自定义类序列化为 Json 字符串的情况。
这是您的简单自定义类:
public class Foo {
private final Date date;
public Foo(Date date) {
this.date = date;
}
}
这里是 Foo
类的自定义序列化程序:
public class FooSerializer implements JsonSerializer<Foo> {
private static SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
@Override
public JsonElement serialize(Foo src, Type typeOfSrc, JsonSerializationContext context) {
final JsonObject object = new JsonObject();
object.addProperty("date", format.format(src.date));
return object;
}
}
如您所见,有一个静态的 SimpleDateFormat
用于将 Data
对象序列化为 String
。
问题来了:SimpleDateFormat
不是线程安全的,保存在 Gson
对象中的 typeAdapters
数组也不是线程安全的.
在这种情况下,如果您使用单个 Gson
实例
new GsonBuilder()
.registerTypeAdapter(Foo.class, new FooSerializer())
.create();
在您的应用程序的不同线程中,这只是时间问题,当您得到错误的数据时,例如:{"date":"Thu, 0015 Oct 2015 21:32:0040 +0600"}
在这种情况下,您可以用类似的方式创建自己的线程安全对象:
public class SimpleDateFormatThreadSafe extends SimpleDateFormat {
private static final long serialVersionUID = 5448371898056188202L;
ThreadLocal<SimpleDateFormat> localSimpleDateFormat;
public SimpleDateFormatThreadSafe() {
super();
localSimpleDateFormat = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat();
}
};
}
public SimpleDateFormatThreadSafe(final String pattern) {
super(pattern);
localSimpleDateFormat = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat(pattern);
}
};
}
public SimpleDateFormatThreadSafe(final String pattern, final DateFormatSymbols formatSymbols) {
super(pattern, formatSymbols);
localSimpleDateFormat = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat(pattern, formatSymbols);
}
};
}
public SimpleDateFormatThreadSafe(final String pattern, final Locale locale) {
super(pattern, locale);
localSimpleDateFormat = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat(pattern, locale);
}
};
}
@Override
public Object parseObject(String source) throws ParseException {
return localSimpleDateFormat.get().parseObject(source);
}
@Override
public String toString() {
return localSimpleDateFormat.get().toString();
}
@Override
public Date parse(String source) throws ParseException {
return localSimpleDateFormat.get().parse(source);
}
// ... here are other overridden methods ...
@Override
public Object clone() {
return localSimpleDateFormat.get().clone();
}
@Override
public int hashCode() {
return localSimpleDateFormat.get().hashCode();
}
@Override
public boolean equals(Object obj) {
return localSimpleDateFormat.get().equals(obj);
}
}
关于android - 在 Android 上,我应该/可以使用一个单例 Gson 对象而不是到处调用 new Gson() 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32905915/