如何将Android Room与外部库提供的POJO一起使用? [英] How to use Android Room with POJOs provided by an external library?

查看:39
本文介绍了如何将Android Room与外部库提供的POJO一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我以前的问题的澄清如何使用在没有字段的实体上使用Android Room?.

This is a clarification of my previous question How to use Android Room on entities without fields?.

我的用例是我正在使用由第三方提供的Java JAR库,其中包含许多POJO,这些POJO我想通过Android Room存储和检索.显然,我无法注释我没有源代码的类中的字段.所提供的POJO的内部结构是一个黑匣子,我所能访问的只是setter和getter.

My use case is that I am using a Java JAR library provided by a third party which contains many POJOs that I want to store and retrieve via Android Room. Clearly I cannot annotate the fields in a class that I don't have the source code for. The internal structure of the POJOs provided is a black box, all I have access to are setters and getters.

例如,想象一下我想将android.graphics.Rect的实例与Room一起使用.

Imagine for example I want to use instances of android.graphics.Rect with Room.

推荐答案

以下是我想出的解决方案,没有一个是完全理想的,但最后一个是不错的.

Here are solutions I came up with, none is completely ideal but the last is decent.

坏:

此选项只是天真地复制库POJO类,并提供了将库POJO与Room POJO之间来回转换的辅助方法.相当丑陋,因为这会使副本变得发散并且不同步,所以我必须在应用程序中来回编写很多代码.

This option is just naively making a copy of the library POJO class and providing helper methods to convert the the Library POJO to and from the Room POJO. Pretty ugly and since this makes copies that can diverge and get out of sync and I have to write a lot of code copying back and forth in my app.

@Entity(tableName = "items")
public class RoomItem {

  @PrimaryKey
  @NonNull
  public String id;
  public String name;
  public Long price

  public LibraryItem to() {
    LibraryItem li = new LibraryItem();
    li.setName(name);
    li.setPrice(price);
  }

  public static RoomItem from(LibraryItem li) {
    RoomItem ri = new RoomItem();
    ri.name = li.getName();
    ri.price = li.getPrice();
  }

}

好的:

在这种情况下,RoomItem是一个包装器类,其中的字段仅用于通知Room有关列和类型,除了id之外,字段中实际上没有存储任何内容,因此它们只是浪费空间.每当我想获取与库方法一起使用的真实库对象时,都必须获取已包装的实例.至少RoomItem和LibraryItem实际上反映了更改.

In this case the RoomItem is a wrapper class with fields that are only used to inform Room about the columns and types, other than id nothing is every actually stored in the fields so they just waste space. Any time I want to get the real library object for use with library methods I have to grab the wrapped instance. At least the RoomItem and LibraryItem actually mirror changes.

@Entity(tableName = "items")
public class RoomItem {

  // I have to put these fields here even though they aren't used to store any
  // data just to make Room happy!
  @PrimaryKey
  @NonNull
  private String id = "";
  private String name;
  private Long price;

  @Ignore
  private final LibraryItem item = new LibraryItem();

  public RoomItem(String id, String name, Long price) {
    this.id = id;
    setName(name);
    setPrice(price);
  }

  @NonNull
  public String getId() {
    return id;
  }

  public void setId(@NonNull String id) {
    this.id = id;
  }

  public String getName() {
    return item.getName();
  }

  public void setName(String name) {
    item.setName(name);
  }

  public Long getPrice() {
    return item.getPrice();
  }

  public void setPrice(Long price) {
    item.setPrice(price);
  }

  public Library getLibraryItem() {
    return item;
  }
}

更好(2.2.0-alpha02或更高版本)

Google修复了我在Room中报告的一个错误,自2.2.0-alpha02起现在可以使用继承.子类中的字段仅用于通知Room保留哪些内容,并且启用minify时,它们实际上会被清除,因此不会浪费内存.此解决方案要求我对父类的内部结构有所了解,因此可以忽略其中的内部内容,例如privateParentField.但是,它比"Okay"示例更好,因为我现在可以将RoomItem的实例传递给采用LibraryItem的方法,而无需编写太多样板.

Google fixed a bug I reported in Room and as of 2.2.0-alpha02 it is now possible to use inheritance. The fields in the child class are just used to inform Room what to persist and when minify is enabled they are actually culled so no memory is wasted. This solution required me to know a bit about the internal structure of the parent class so I could ignore things inside it such as privateParentField. However it's better than the "Okay" example because I can now pass instances of the RoomItem around to methods that take LibraryItem and I don't need to write much boilerplate.

@Entity(tableName = "items", ignoredColumns = "privateParentField")
public class RoomItem extends LibraryItem {

  // I have to put these fields here even though they aren't used to store any
  // data just to make Room happy!
  @PrimaryKey
  @NonNull
  private String id;
  private String name;
  private Long price;

  public RoomItem(String id, String name, Long price) {
    setId(id);
    setName(name);
    setPrice(price);
  }

}

这篇关于如何将Android Room与外部库提供的POJO一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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