android - 在 Android 上,我应该/可以使用一个单例 Gson 对象而不是到处调用 new Gson() 吗?

标签 android gson

我想知道是否应该在我的应用程序中保留一个 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/

相关文章:

java - 如何解析对 Java 对象列表的嵌套 JSON 响应

android - 测试不便:Android Studio JUnit vs Gradle基于:Android Studio忽略了testOptions

java - 如何从 firebase 服务器获取图像和视频到我的博客应用程序?

android - 为 android 手机和平板电脑创建不同的布局

java - 需要帮助从 Firestore (Android) 检索 HashMap 值

android - 使用 APK 证书创建 SSL 上下文

android - 使用 GSON 进行 JSON 反序列化

java - 更新 json 类型的列值失败,出现异常

java - Gson将小写JSON反序列化为驼峰式Class对象

java - 是否可以用 Gson 扁平化 JSON 层次结构?