在Gson反序列化期间使用Dagger进行依赖注入
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Gson反序列化期间使用Dagger进行依赖注入相关的知识,希望对你有一定的参考价值。
在我的应用程序中,我创建的对象不是由我创建的,而是由Gson反序列化器创建的。这些对象需要引用单例实例,我可以使用构造函数注入来提供其他任何地方。
但是,像这样访问Gson调用的默认构造函数中的相关组件
DaggerExampleComponent.builder().build().inject(this)
不会重复使用其他地方注入的单例 - 从我的理解,这是因为构建器实际上会创建一个新的ExampleComponent
实例,它不了解现有的实例。
我的解决方法是在instance
中保持静态ExampleComponent
字段和getter,但我想知道是否有一种最佳实践,如何用另一种方法实现相同的事情。
编辑正在使用Android Room Persistence library对从数据库检索的数据进行反序列化。通过在静态方法上使用@TypeConverter
批注来实现将数据转换为自定义对象,静态方法在从数据库中检索元素时会隐式调用。这使我无法在那里注入创建的对象 - 转换器是未实例化的静态类中的静态方法,因此我无法将DaggerComponent对象传递给它以用于注入创建的实例,如下面的Thorben所建议的那样。
Disclaimer
我很久没和Dagger合作了。用一粒盐取下面的溶液!该解决方案适用于我本地。
没有Dagger ExampleComponent
问题的一个答案可能是,使用自定义的JsonDeserializer接口实现,它将要注入的对象的实例作为构造函数参数。
你可以编写自己的反序列化器,将单例实例注入到反序列化的对象中,如下所示:
class MyJsonDeserializer implements JsonDeserializer<MyObject> {
private final MyComponent singleton;
public MyJsonDeserializer(MyComponent component) {
this.singleton = component;
}
public MyObject deserialize(JsonElement json, Type tye, JsonDeserializationContext context) throws JsonParseException {
// you could here parse some arguments
return new MyObject(singleton);
}
}
你会这样注册:
MyComponent component = ...
Gson gson = new GsonBuilder().registerTypeAdapter(MyObject.class, new MyJsonDeserializer(component)).create();
如果要注入MyComponent类,则应确保每个创建的对象都具有MyComponent对象的相同实例。
我个人更喜欢这个解决方案,不要混淆Dagger和Gson。
使用Dagger
您也可以更改代码以在所述JsonDeserializer中使用DaggerAppComponent,如下所示:
class MyJsonDeserializer implements JsonDeserializer<MyObject> {
private final DaggerAppComponent singletonProvider;
public MyJsonDeserializer(DaggerAppComponent componentProvdider) {
this.singletonProvider = componentProvider;
}
public MyObject deserialize(JsonElement json, Type tye, JsonDeserializationContext context) throws JsonParseException {
// you could here parse some arguments
MyObject object = ...
singletonProvider.inject(object);
return object;
}
}
并像这样更改注册:
DaggerAppComponent componentBuilder = DaggerExampleComponent.builder().build();
Gson gson = new GsonBuilder().registerTypeAdapter(MyObject.class, new MyJsonDeserializer(componentBuilder)).create();
UPDATE
由于新的信息,我建议增强现有的类,用于android Room Persistence库(包含带注释的方法的类),如下所示:
class Convert {
static DaggerAppComponent singletonProvider;
@TypeConverter
public static MyObject convert(String arg) {
Gson gson = new GsonBuilder().registerTypeAdapter(MyObject.class, new MyJsonDeserializer(componentBuilder)).create();
return gson.fromJson(arg, MyObject.class);
}
@TypeConverter
public static String fromArrayLisr(MyObject object) {
Gson gson = new Gson();
String json = gson.toJson(v);
return json;
}
}
我从thetechguru那里得到了一些灵感。此外,这假设与上述相同的JsonDeserializer。
由于我不知道实际的参数,在asume String中作为这个typeconverter的参数。在那里插入相应的类型。
为了有效地使用它,在代码中的某个地方(在完成任何数据库相关的东西之前),应该调用它:
Convert.singletonProvider = DaggerExampleComponent.builder().build();
这将允许Convert类查看正确的DaggerAppComponent。
这可能仍有问题。这是一个race condition,承认静态变量的null状态。如果很快调用数据库,结果将是NullpointerException,因为尚未设置静态字段。为了抵消这一点,你可以使用信号量(或任何semilliar)来创造某种障碍。使用信号量,这将包括一个允许0的简单信号量。在使用变量调用获取和释放之前。在设置变量之后(在此类之外),在其上调用release一次。
这不是一个好的解决方案(在软件设计方面),但应该可以解决问题。
以上是关于在Gson反序列化期间使用Dagger进行依赖注入的主要内容,如果未能解决你的问题,请参考以下文章