在我的应用程序中,我不是由我而是由Gson反序列化器创建的对象。这些对象需要引用单例实例,我可以使用构造函数注入在其他地方提供这些实例。
但是,像这样通过Gson调用的默认构造函数访问相关组件
5 #length of the array
1 2 3 4 5 #inputs separated by space
不会重用注入到其他地方的单例-从我的理解中,这是因为构建器实际上将创建DaggerExampleComponent.builder().build().inject(this)
的新实例,而该实例对现有实例一无所知。
我的解决方法是在ExampleComponent
内保留一个静态instance
字段以及一个吸气剂,但是我想知道是否存在使用另一种方法实现同一目标的最佳实践。
编辑:正在对使用Android Room Persistence library从数据库中检索到的数据进行反序列化。通过在静态方法上使用ExampleComponent
批注来实现将数据转换为自定义对象的方法,当从数据库中检索元素时会隐式调用该批注。这阻止了我将创建的对象注入到那里-转换器是未实例化的静态类中的静态方法,因此我无法将DaggerComponent对象传递给它以用于注入创建的实例,如下面的Thorben建议的那样。 / p>
答案 0 :(得分:0)
我很久没有和Dagger合作了。盐以下采取解决方案!该解决方案在本地对我有效。
问题的一个答案可能是,使用自定义的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。
您还可以像这样在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();
更新
由于有了新信息,我建议增强现有类,该类用于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。
由于我不知道实际参数,因此我将String假定为此typeconverter的参数。在其中插入相应的类型。
要有效地使用此代码,请在代码中的某个位置(在完成任何与数据库相关的工作之前),应将其称为:
Convert.singletonProvider = DaggerExampleComponent.builder().build();
这将允许Convert类查看正确的DaggerAppComponent。
这可能仍然有问题。这是race condition,属于静态变量的null状态。如果很快调用数据库,结果将是NullpointerException,因为尚未设置静态字段。为了解决这个问题,您可以使用信号量(或其他半音)来创建某种屏障。对于信号量,这将包括一个具有0个许可的简单信号量。在使用变量之前,先获取并释放它。设置完变量后(在此类之外),对其调用一次release。
这不是一个好的解决方案(就软件设计而言),但是应该可以解决问题。