【问题标题】:Accessing and Storing multiple POJO classes in Room在 Room 中访问和存储多个 POJO 类
【发布时间】:2018-09-24 11:07:33
【问题描述】:

我有多个 POJO 类作为主 POJO 类的类型,我使用它来使用 Retrofit 解析 json 数据。所以我为第一级 Pojo 提供了类型转换器,但是我在读取存储的数据时遇到了麻烦,因为它的格式不正确。

这是我的 POJO 类

@Entity(tableName = "entry")
public class Entry implements Parcelable {

    @NonNull
    @PrimaryKey
    @SerializedName("id")
    private FeedID feedId;
    @SerializedName("title")
    private Title EntryTitle;
    @SerializedName("im:image")
    private List<Image> image;
    @SerializedName("summary")
    private Summary summary;

    public Entry(){}

    public FeedID getFeedId() {
        return feedId;
    }

    public void setFeedId(FeedID feedId) {
        this.feedId = feedId;
    }

    public Title getEntryTitle() {
        return EntryTitle;
    }

    public void setEntryTitle(Title entryTitle) {
        this.EntryTitle = entryTitle;
    }

    public List<Image> getImage() {
        return image;
    }

    public void setImage(List<Image> image) {
        this.image = image;
    }

    public Summary getSummary() {
        return summary;
    }

    public void setSummary(Summary summary) {
        this.summary = summary;
    }

    @SuppressWarnings("unused")
    public static final Parcelable.Creator<Entry> CREATOR = new Parcelable.Creator<Entry>() {
        @Override
        public Entry createFromParcel(Parcel in) {
            return new Entry(in);
        }

        @Override
        public Entry[] newArray(int size) {
            return new Entry[size];
        }
    };

    protected Entry(Parcel in) {
        feedId = (FeedID) in.readValue(FeedID.class.getClassLoader());
        EntryTitle = (Title) in.readValue(Title.class.getClassLoader());
        if (in.readByte() == 0x01) {
            image = new ArrayList<Image>();
            in.readList(image, Image.class.getClassLoader());
        } else {
            image = null;
        }
        summary = (Summary) in.readValue(Summary.class.getClassLoader());
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeValue(feedId);
        dest.writeValue(EntryTitle);
        if (image == null) {
            dest.writeByte((byte) (0x00));
        } else {
            dest.writeByte((byte) (0x01));
            dest.writeList(image);
        }
        dest.writeValue(summary);
    }

    public class Title implements Parcelable {
        private String label;

        public String getLabel() {
            return label;
        }

        public void setLabel(String label) {
            this.label = label;
        }

        @SuppressWarnings("unused")
        public final Parcelable.Creator<Title> CREATOR = new Parcelable.Creator<Title>() {
            @Override
            public Title createFromParcel(Parcel in) {
                return new Title(in);
            }

            @Override
            public Title[] newArray(int size) {
                return new Title[size];
            }
        };

        protected Title(Parcel in) {
            label = in.readString();
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(label);
        }
    }

    public class Image implements Parcelable {
        private String label;

        public String getLabel() {
            return label;
        }

        public void setLabel(String label) {
            this.label = label;
        }

        @SuppressWarnings("unused")
        public final Parcelable.Creator<Image> CREATOR = new Parcelable.Creator<Image>() {
            @Override
            public Image createFromParcel(Parcel in) {
                return new Image(in);
            }

            @Override
            public Image[] newArray(int size) {
                return new Image[size];
            }
        };

        protected Image(Parcel in) {
            label = in.readString();
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(label);
        }
    }

    public class Summary implements Parcelable {
        private String label;

        public String getLabel() {
            return label;
        }

        public void setLabel(String label) {
            this.label = label;
        }

        @SuppressWarnings("unused")
        public final Parcelable.Creator<Summary> CREATOR = new Parcelable.Creator<Summary>() {
            @Override
            public Summary createFromParcel(Parcel in) {
                return new Summary(in);
            }

            @Override
            public Summary[] newArray(int size) {
                return new Summary[size];
            }
        };

        protected Summary(Parcel in) {
            label = in.readString();
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(label);
        }
    }

    public class FeedID implements Parcelable {

        private Attributes attributes;

        public Attributes getAttributes() {
            return attributes;
        }

        public void setAttributes(Attributes attributes) {
            this.attributes = attributes;
        }


        @SuppressWarnings("unused")
        public final Parcelable.Creator<FeedID> CREATOR = new Parcelable.Creator<FeedID>() {
            @Override
            public FeedID createFromParcel(Parcel in) {
                return new FeedID(in);
            }

            @Override
            public FeedID[] newArray(int size) {
                return new FeedID[size];
            }
        };

        protected FeedID(Parcel in) {
            attributes = (Attributes) in.readValue(Attributes.class.getClassLoader());
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeValue(attributes);
        }
    }

    public class Attributes implements Parcelable {

        @SerializedName("im:id")
        private String id;

        public String getIm() {
            return id;
        }

        public void setIm(String im) {
            this.id = im;
        }

        @SuppressWarnings("unused")
        public final Parcelable.Creator<Attributes> CREATOR = new Parcelable.Creator<Attributes>() {
            @Override
            public Attributes createFromParcel(Parcel in) {
                return new Attributes(in);
            }

            @Override
            public Attributes[] newArray(int size) {
                return new Attributes[size];
            }
        };

        protected Attributes(Parcel in) {
            id = in.readString();
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(id);
        }
    }
}

这是我的 TypeConverter 类

    public class RoomTypeConverters {

    @TypeConverter
    public static String toString(Entry.Title value) {
        Gson gson = new Gson();
        String json = gson.toJson(value);
        return json;
    }

    @TypeConverter
    public static Entry.Title toTitle(String value) {
        Type listType = new TypeToken<Entry.Title>() {
        }.getType();
        return new Gson().fromJson(value, listType);
    }

    @TypeConverter
    public static String toString(Entry.FeedID value) {
        Gson gson = new Gson();
        String json = gson.toJson(value);
        return json;
    }

    @TypeConverter
    public static Entry.FeedID toFeedID(String value) {
        Type listType = new TypeToken<Entry.FeedID>() {
        }.getType();
        return new Gson().fromJson(value, listType);
    }

    @TypeConverter
    public static String toString(Entry.Summary value) {
        Gson gson = new Gson();
        String json = gson.toJson(value);
        return json;
    }

    @TypeConverter
    public static Entry.Summary toSummary(String value) {
        Type listType = new TypeToken<Entry.Summary>() {
        }.getType();
        return new Gson().fromJson(value, listType);
    }

    @TypeConverter
    public static String toString(List<Entry.Image> value) {
        Gson gson = new Gson();
        String json = gson.toJson(value);
        return json;
    }

    @TypeConverter
    public static List<Entry.Image> toImage(String value) {
        Type listType = new TypeToken<Entry.Summary>() {
        }.getType();
        return new Gson().fromJson(value, listType);
    }
}

我必须为一个字段创建多个这样的 POJO 吗?我们还有其他选择吗?

【问题讨论】:

    标签: android android-room


    【解决方案1】:

    是的,要保存 POJO,您必须为它定义一个类(内部类或普通类)。

    但我从您的数据架构中了解到,您可能有一个 复杂 数据存储服务器端,并且您希望在您的应用中使用该数据的 子集。您的 POJO 可以简化,因此您可以创建一个名为 EntryRecord 的类,并为它定义一个简单的 setter 和 getter,如下所示:

    @Entity(tableName = "entry")
    public class EntryRecord {
    
        @NonNull
        @PrimaryKey
        @SerializedName("id")
        private String feedId;
        @SerializedName("title")
        private StringEntryTitle;
        @SerializedName("im:image")
        private String[] image;
        @SerializedName("summary")
        private String summary;
    
        public EntryRecord(Entry entry){
            //Resolve primitive values from Entry class attributes..
        }
    
        public Entry getEntry(){
            Entry entry = new Entry();
            //Resolve entry values from primitive ones...
            return entry ;
        }
    }
    

    ,现在你要做的就是使用这个类来保存和恢复你的数据,你可以让你的DAOabstract在保存之前转换你的POJO,反之亦然。

    P.S: 如果你对这么多单变量类的复杂 Schema 没有任何用处,我真的建议你定义自定义 GSON serializer/deserializer 来转换复杂的 POJO从一开始就简化一个;从您的代码库中完全删除如此复杂的架构。

    【讨论】:

      【解决方案2】:

      所以经过一些研究,我发现了一个注释,如果你有多个内部类,房间会处理它,你不必为它创建任何 TypeConverters。

      @Embedded 可用作 Entity 或 Pojo 字段的注解,表示可以引用嵌套字段(即注解字段的类的字段)直接在 SQL 查询中。

      例如,如果您有 2 个类:

          public class Coordinates {
             double latitude;
             double longitude;
         }
         public class Address {
             String street;
             @Embedded
             Coordinates coordinates;
         }
      

      在将 SQLite 行映射到 Address 时,Room 会将纬度和经度视为 Address 类的字段。

      来源:Documentation

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-08
        • 2019-05-24
        • 1970-01-01
        • 1970-01-01
        • 2015-07-21
        相关资源
        最近更新 更多