带有Gson序列化的RealmObjects的继承组合 [英] Composition over inheritance for RealmObjects with Gson serialization

查看:109
本文介绍了带有Gson序列化的RealmObjects的继承组合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在考虑Realm作为一个数据库解决方案,因为各种原因,但是目前在Nougat中引发的大规模TransactionTooLargeException已经让我不得不重新修改我现有的基于ActiveAndroid的数据库体系结构,它有自己的恼人的限制。难点在于Realm不支持继承( https://github.com/realm/ realm-java / issues / 761 ),他们似乎并不特别着急去解决它。相反,他们推荐使用合成而不是继承,但我无法弄清楚如何使用Gson / Json反序列化进行工作。



示例:



超级动物:带有子类的动物狗和德国牧羊犬

  public class Animal {

private int numLegs;

private boolean hasFur;
}

public class Dog extends Animal {
private String color;

私人布尔canDoTricks;
}

public class GermanShepherd extends Dog {

public boolean isGuardDog;

public boolean isAtRiskOfHipDysplasia()
}

这是一个超级罐头的例子,只是为了说明)。



现在让我们来看看这个json的样子:



< pre $ {
numLegs:4,
hasFur:true,
color:Black& Brown,
canDoTricks:true,
isGuardDog:true,
isAtRiskofHipDysplasia:false
}

现在,我不能修改Json,因为它是一个给我的API。



在这个答案: https://stackoverflow.com/a/41552457/4560689 ,它似乎有可能在一个非常这种做法有点令人费解,但答案指出,存在限制,包括序列化会出错。由于服务器只以json格式进行会话,并不涉及疯狂的组合,因此会出现问题。



我可以写一个自定义的Gson解串器/序列化程序来使其工作?如果是这样,那会是什么样子?我基本上需要能够将json有效载荷转换为 N 对象,其中 N-1 对象嵌套在基础对象内。



因此,对于组合(注意这不一定是Realm组合,仅仅是一个例子,因为它看起来像Realm必须使用一些奇怪的界面组合),我会有一个类如下所示:

  public class GermanShepherd {
public animal animal;
公狗狗;

//在这里生成一堆委托方法
}

我吠叫了错误的树吗?感觉Realm可能不适用于我想要做的事情,并且继承被构建到我在多个地方使用的API中,特别是在我想要保留的对象中,因此我必须找出解决方法或使用其他解决方案。 ActiveAndroid(我现在使用的)也是一个不太理想的解决方案,我生病时死于处理死锁,崩溃,查询后台线程,现在会导致崩溃,如果数据太大,无法通过意图等...与SQLite的所有问题。我愿意解决我的主要问题或解决此问题的替代方案。感谢您的帮助!

解决方案

您应该为每个拼合的具体类创建一个新的RealmObject类,并映射JSON表示为了保留继承,您可以通过从相互继承的接口继承getters / setter来模拟它。

  public interface IAnimal extends RealmModel {
int getNumberOfLegs();
void setNumberOfLegs(int legs);
boolean getHasFur();
void setHasFur(boolean hasFur);
}

public interface IDog extends IAnimal {
String getColor();
void setColor(String color);
boolean getCanDoTricks();
void setCanDoTricks();
}

public interface IGermanShepherd extends IDog {
boolean getIsGuardDog();
void setIsGuardDog(boolean isGuardDog);
boolean getIsAtRiskOfHipDysplasia();
void setIsAtRiskOfHipDysplasia(boolean isAtRisk);
}

因为你可以做

  public class GermanShepard 
extends RealmObject
实现IGermanShepard {
private int numLegs;
private boolean hasFur;
私有字符串颜色;
私人布尔canDoTricks;
private boolean isGuardDog;
private boolean isAtRiskofHipDysplasia;

//继承getters / setters
}

你可以甚至使存储库类脱离它

  public abstract class AnimalRepository< T extends IAnimal> {
protected Class< T> clazz中;

public AnimalRepository(Class< T> clazz){
this.clazz = clazz;
}

public RealmResults< T> findAll(Realm realm){
return realm.where(clazz).findAll();
}
}

@Singleton
public class GermanShepardRepository extends AnimalRepository< GermanShepard> {
@Inject
public GermanShepardRepository(){
super(GermanShepard.class);
}
}

然后

  @Inject 
GermanShepardRepository germanShepardRepository;

RealmResults< GermanShepard> results = germanShepardRepository.findAll(realm);






但你确实可以将它们合并成一个类,然后给它一个字符串类型; 参数来知道它最初是什么类型。这可能比拥有所有这些GermanShepards更好。


I'm considering Realm as a database solution for various reasons, but the big one currently being the TransactionTooLargeException now being thrown in Nougat has made it so I have to rework my current database architecture, based on ActiveAndroid, which has its own annoying limitations. The difficulty is that Realm does not support inheritance (https://github.com/realm/realm-java/issues/761) and they don't seem in any particular hurry to get around to it. Instead, they recommend using composition over inheritance, but I can't figure out how to make that work with Gson/Json deserialization.

Example:

Superclass: Animal, with subclasses Dog and German Shepherd

public class Animal {

    private int numLegs;

    private boolean hasFur;
}

public class Dog extends Animal {
    private String color;

    private boolean canDoTricks;
}

public class GermanShepherd extends Dog {

    public boolean isGuardDog;

    public boolean isAtRiskOfHipDysplasia()
}

(Sorry, this is a super canned example, just to illustrate).

Now let's say the json for this looks like:

{
  "numLegs" : 4,
  "hasFur" : true,
  "color" : "Black & Brown",
  "canDoTricks" : true,
  "isGuardDog" : true,
  "isAtRiskofHipDysplasia" : false
}

Now, I cannot modify the Json because it's an API that's giving it to me.

Looking at this answer: https://stackoverflow.com/a/41552457/4560689, it appears it is possible in a very hacky way to make it sort of work, but the answer notes that there are limitations including that the serialization would be wrong. Since the server only talks in the json format that doesn't involve crazy composition, this presents a problem.

Can I write a custom Gson deserializer/serializer to make this work? If so, what would that look like? I basically need to be able to convert a json payload into up to N objects, where N - 1 objects are nested inside the base object.

So with composition (note this isn't necessarily "Realm" composition, just an example, since it looks like Realm has to use some weird form of interface-composition), I'd have a class like below:

public class GermanShepherd {
    public Animal animal;
    public Dog dog;

   // Generate a bunch of delegate methods here
}

Am I barking up the wrong tree? It feels like Realm might not work for what I'm trying to do, and inheritance is built into the API I'm using in multiple places, and specifically in the objects I want to persist, so I have to either figure out a workaround or use another solution. ActiveAndroid (what I'm using now) is also a less than ideal solution and I'm sick to death of dealing with skirting around deadlocks, crashes, querying on background threads that now cause crashes if the data is too big to pass in an Intent, etc...all issues with SQLite. I'm open to solutions to my main question or to alternatives that would solve this problem. Thanks in advance for your help!

解决方案

You should create a new RealmObject class for each flattened concrete class, and map your JSON representation to them.

To retain inheritance, you can simulate it by inheriting getters/setters from interfaces that inherit from one another.

public interface IAnimal extends RealmModel {    
    int getNumberOfLegs();
    void setNumberOfLegs(int legs);
    boolean getHasFur();
    void setHasFur(boolean hasFur);
}

public interface IDog extends IAnimal {
    String getColor();
    void setColor(String color);
    boolean getCanDoTricks();
    void setCanDoTricks();
}

public interface IGermanShepherd extends IDog {
    boolean getIsGuardDog();
    void setIsGuardDog(boolean isGuardDog);
    boolean getIsAtRiskOfHipDysplasia();
    void setIsAtRiskOfHipDysplasia(boolean isAtRisk);
}

Because then you can do

public class GermanShepard 
    extends RealmObject 
    implements IGermanShepard {
      private int numLegs;
      private boolean hasFur;
      private String color;
      private boolean canDoTricks;
      private boolean isGuardDog;
      private boolean isAtRiskofHipDysplasia;

      // inherited getters/setters
}

You can even make repository class out of it

public abstract class AnimalRepository<T extends IAnimal> {
     protected Class<T> clazz;

     public AnimalRepository(Class<T> clazz) {
         this.clazz = clazz;
     }

     public RealmResults<T> findAll(Realm realm) {
         return realm.where(clazz).findAll();
     }
}

 @Singleton
 public class GermanShepardRepository extends AnimalRepository<GermanShepard> {
      @Inject
      public GermanShepardRepository() {
          super(GermanShepard.class);
      }
 }

And then

@Inject
GermanShepardRepository germanShepardRepository;

RealmResults<GermanShepard> results = germanShepardRepository.findAll(realm);


But you can indeed merge them into one class and then give it a String type; parameter to know what type it originally was. That's probably even better than having all these GermanShepards.

这篇关于带有Gson序列化的RealmObjects的继承组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆