如何将 SparseArray 保存在 Room 数据库中?
How can I save a SparseArray in a Room database?
我正在尝试将 SparseArray 保存在 Room 数据库中,但无法对其进行编译。我不断收到 "Not sure how to convert a Cursor to this method's return type" 错误消息以及 "The query returns some columns [plannerLineData] which are not use by android.util.SparseArray."
我已经尝试在 PlannerLine 实体中单独使用单个字段和单独的 PlannerLineData class。
我有数据转换器可以将 SparseArray 转换为 String 并将 String 转换回 SparseArray。
我已经检查了几个关于Whosebug的问题,并在其他项目中成功地使用了Date to Long和Long to Date转换器,但我似乎在某处遗漏了一些东西。
数据文件:
@Entity
public class PlannerLine implements Serializable {
private static final long serialVersionUID = 1L;
@TypeConverters(Converters.class)
@PrimaryKey
@SerializedName("planner_line")
@NonNull
public SparseArray plannerLineData;
public SparseArray getPlannerLineData() {
return plannerLineData;
}
public void setPlannerLineData(SparseArray plannerLineData) {
this.plannerLineData = plannerLineData;
}
public class PlannerLineData implements Serializable {
@SerializedName("lineId")
public int lineId;
@SerializedName("plan_text")
public String planText;
public int getLineId() {
return lineId;
}
public void setLineId(int lineId) {
this.lineId = lineId;
}
public String getPlanText() {
return planText;
}
public void setPlanText(String planText) {
this.planText = planText;
}
}
DAO问题领域:
@Dao
public interface PlannerDao {
@Query("SELECT * from PlannerLine")
public SparseArray getPlannerLine(); <---Doesn't like this line
我也试过返回 SparseArray<PlannerLine>
和 SparseArray<PlannerLineData>
,但不高兴。
转换器class:
public class Converters {
@TypeConverter
public static String sparseArrayToString(SparseArray sparseArray) {
if (sparseArray == null) {
return null;
}
int size = sparseArray.size();
if (size <= 0) {
return "{}";
}
StringBuilder buffer = new StringBuilder(size * 28);
buffer.append('{');
for (int i = 0; i < size; i++) {
if (i > 0) {
buffer.append("-,- ");
}
int key = sparseArray.keyAt(i);
buffer.append(key);
buffer.append("-=-");
Object value = sparseArray.valueAt(i);
buffer.append(value);
}
buffer.append('}');
return buffer.toString();
}
@TypeConverter
public static SparseArray stringToSparseArray(String string) {
if (string == null) {
return null;
}
String entrySeparator = "-=-";
String elementSeparator = "-,-";
SparseArray sparseArray = new SparseArray();
String[] entries = StringUtils.splitByWholeSeparator(string, elementSeparator);
for (int i = 0; i < entries.length; i++) {
String[] parts = StringUtils.splitByWholeSeparator(entries[i], entrySeparator);
int key = Integer.parseInt(parts[0]);
String text = parts[1];
sparseArray.append(key, text);
}
return sparseArray;
}
建议将不胜感激。谢谢
编辑:
我对这个应用程序的最初设想是将所有计划行存储在一个 SparseArray
中,以及两个额外的 SparseIntArrays
(我之前没有提到,因为解决方案类似于SparseArray
) 来保存计划线如何相互作用的信息。
阅读完@dglozano 的有用回复后,我决定重新设计应用程序以仅将常规数据库文件存储在 Room 中并将数据加载到 SparseArray
(以及两个 SparseIntArrays
) 在启动时,在应用程序处于活动状态时仅使用内存 SparseArray
和 SparseIntArrays
,然后在 onStop()
期间将稀疏数组中的更改写入数据库。我也在考虑在通过应用程序工作时在后台更新数据库。
因为@dglozano 提供的答案和建议让我做出了重新设计的决定,所以我接受他的答案作为解决方案。
感谢您的帮助。
看来你的转换是正确的。但是,问题出在您的 DAO 查询中:
@Query("SELECT * from PlannerLine") // This returns a List of PlannerLine, not a SparseArray
public SparseArray getPlannerLine(); // The return type is SparseArray, not a List of PlannerLine
因此,您可以尝试两种不同的方法:
1 - 将查询更改为 @Query("SELECT plannerLineData FROM PlannerLine WHERE lineId == :lineId")
,以便查询 return 是 PlannerLine
内的 SparseArray
,id 为 lineId
。您应该更改方法签名,以便它接受参数 lineId
@Query("SELECT plannerLineData FROM PlannerLine WHERE lineId == :lineId")
public SparseArray getPlannerLine(int lineId);
2 - 如果您想 return 完整的 PlannerLine
对象然后访问其 SparseArray
字段,那么您应该更改 return 类型。您还应该将 lineId
参数仅添加到 return 一条记录,而不是存储在数据库 table.
中的所有 PlannerLine
的列表
@Query("SELECT * FROM PlannerLine WHERE lineId == :lineId")
public PlannerLine getPlannerLine(int lineId);
更新
如果你想得到一个 List<PlannerLine>
并且所有 PlannerLine
都存储在数据库中,请在你的 Dao 中使用以下查询。
@Query("SELECT * FROM PlannerLine")
public List<PlannerLine> getAllPlannerLines();
然后就可以像往常一样访问列表中每个PlannerLine的SparseArray了
我正在尝试将 SparseArray 保存在 Room 数据库中,但无法对其进行编译。我不断收到 "Not sure how to convert a Cursor to this method's return type" 错误消息以及 "The query returns some columns [plannerLineData] which are not use by android.util.SparseArray."
我已经尝试在 PlannerLine 实体中单独使用单个字段和单独的 PlannerLineData class。
我有数据转换器可以将 SparseArray 转换为 String 并将 String 转换回 SparseArray。
我已经检查了几个关于Whosebug的问题,并在其他项目中成功地使用了Date to Long和Long to Date转换器,但我似乎在某处遗漏了一些东西。
数据文件:
@Entity
public class PlannerLine implements Serializable {
private static final long serialVersionUID = 1L;
@TypeConverters(Converters.class)
@PrimaryKey
@SerializedName("planner_line")
@NonNull
public SparseArray plannerLineData;
public SparseArray getPlannerLineData() {
return plannerLineData;
}
public void setPlannerLineData(SparseArray plannerLineData) {
this.plannerLineData = plannerLineData;
}
public class PlannerLineData implements Serializable {
@SerializedName("lineId")
public int lineId;
@SerializedName("plan_text")
public String planText;
public int getLineId() {
return lineId;
}
public void setLineId(int lineId) {
this.lineId = lineId;
}
public String getPlanText() {
return planText;
}
public void setPlanText(String planText) {
this.planText = planText;
}
}
DAO问题领域:
@Dao
public interface PlannerDao {
@Query("SELECT * from PlannerLine")
public SparseArray getPlannerLine(); <---Doesn't like this line
我也试过返回 SparseArray<PlannerLine>
和 SparseArray<PlannerLineData>
,但不高兴。
转换器class:
public class Converters {
@TypeConverter
public static String sparseArrayToString(SparseArray sparseArray) {
if (sparseArray == null) {
return null;
}
int size = sparseArray.size();
if (size <= 0) {
return "{}";
}
StringBuilder buffer = new StringBuilder(size * 28);
buffer.append('{');
for (int i = 0; i < size; i++) {
if (i > 0) {
buffer.append("-,- ");
}
int key = sparseArray.keyAt(i);
buffer.append(key);
buffer.append("-=-");
Object value = sparseArray.valueAt(i);
buffer.append(value);
}
buffer.append('}');
return buffer.toString();
}
@TypeConverter
public static SparseArray stringToSparseArray(String string) {
if (string == null) {
return null;
}
String entrySeparator = "-=-";
String elementSeparator = "-,-";
SparseArray sparseArray = new SparseArray();
String[] entries = StringUtils.splitByWholeSeparator(string, elementSeparator);
for (int i = 0; i < entries.length; i++) {
String[] parts = StringUtils.splitByWholeSeparator(entries[i], entrySeparator);
int key = Integer.parseInt(parts[0]);
String text = parts[1];
sparseArray.append(key, text);
}
return sparseArray;
}
建议将不胜感激。谢谢
编辑:
我对这个应用程序的最初设想是将所有计划行存储在一个 SparseArray
中,以及两个额外的 SparseIntArrays
(我之前没有提到,因为解决方案类似于SparseArray
) 来保存计划线如何相互作用的信息。
阅读完@dglozano 的有用回复后,我决定重新设计应用程序以仅将常规数据库文件存储在 Room 中并将数据加载到 SparseArray
(以及两个 SparseIntArrays
) 在启动时,在应用程序处于活动状态时仅使用内存 SparseArray
和 SparseIntArrays
,然后在 onStop()
期间将稀疏数组中的更改写入数据库。我也在考虑在通过应用程序工作时在后台更新数据库。
因为@dglozano 提供的答案和建议让我做出了重新设计的决定,所以我接受他的答案作为解决方案。
感谢您的帮助。
看来你的转换是正确的。但是,问题出在您的 DAO 查询中:
@Query("SELECT * from PlannerLine") // This returns a List of PlannerLine, not a SparseArray
public SparseArray getPlannerLine(); // The return type is SparseArray, not a List of PlannerLine
因此,您可以尝试两种不同的方法:
1 - 将查询更改为 @Query("SELECT plannerLineData FROM PlannerLine WHERE lineId == :lineId")
,以便查询 return 是 PlannerLine
内的 SparseArray
,id 为 lineId
。您应该更改方法签名,以便它接受参数 lineId
@Query("SELECT plannerLineData FROM PlannerLine WHERE lineId == :lineId")
public SparseArray getPlannerLine(int lineId);
2 - 如果您想 return 完整的 PlannerLine
对象然后访问其 SparseArray
字段,那么您应该更改 return 类型。您还应该将 lineId
参数仅添加到 return 一条记录,而不是存储在数据库 table.
PlannerLine
的列表
@Query("SELECT * FROM PlannerLine WHERE lineId == :lineId")
public PlannerLine getPlannerLine(int lineId);
更新
如果你想得到一个 List<PlannerLine>
并且所有 PlannerLine
都存储在数据库中,请在你的 Dao 中使用以下查询。
@Query("SELECT * FROM PlannerLine")
public List<PlannerLine> getAllPlannerLines();
然后就可以像往常一样访问列表中每个PlannerLine的SparseArray了