首页 > 解决方案 > 如何将 SparseArray 保存在 Room 数据库中?

问题描述

我正在尝试将 SparseArray 持久保存在 Room 数据库中,但无法对其进行编译。我不断收到“不确定如何将光标转换为此方法的返回类型”错误消息以及“查询返回一些列 [plannerLineData] 未被 android.util.SparseArray 使用。”

我曾尝试单独使用 PlannerLine 实体中的单个字段和单独的 PlannerLineData 类。

我有数据转换器将 SparseArray 转换为 String 并将 String 转换回 SparseArray。

我检查了有关 stackoverflow 的几个问题,并在其他项目中成功使用了 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>and SparseArray<PlannerLineData>,但没有任何乐趣。

转换器类:

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 提供的答案和建议让我做出了重新设计的决定,所以我接受他的回答作为解决方案。

谢谢您的帮助。

标签: android-roomandroid-sparsearray

解决方案


看来您正在正确地进行转换。但是,问题出在您的 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 更改为@Query("SELECT plannerLineData FROM PlannerLine WHERE lineId == :lineId"),以便查询返回带有 id的SparseArray内部。您应该更改方法签名,以便它接受参数PlannerLinelineIdlineId

@Query("SELECT plannerLineData FROM PlannerLine WHERE lineId == :lineId")
public SparseArray getPlannerLine(int lineId); 

2 - 如果要返回完整PlannerLine对象然后访问其SparseArray字段,则应更改返回类型。您还应该添加lineId参数以仅返回一条记录,而不是所有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。


推荐阅读