Как я могу сохранить SparseArray в базе данных комнат? - PullRequest
1 голос
/ 23 апреля 2019

Я пытаюсь сохранить 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> и 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;
}

Предложения будут оценены. Спасибо

Edit:

Мое первоначальное видение этого приложения состояло в том, чтобы хранить все линии плана в одной SparseArray вместе с двумя дополнительными SparseIntArrays (о которых я раньше не упоминал, поскольку решение будет похоже на SparseArray) для содержит информацию о том, как линии плана взаимодействуют друг с другом.

Прочитав полезные ответы @ dglozano, я решил переделать приложение, чтобы просто хранить обычные файлы БД в Room и загружать данные в SparseArray (и два SparseIntArrays) при запуске, использовать только в памяти SparseArray и SparseIntArrays, пока приложение активно, затем записать изменения в разреженных массивах в БД во время onStop(). Я также рассматриваю возможность обновления БД в фоновом режиме при работе через приложение.

Поскольку ответы и предложения, предоставленные @dglozano, привели меня к решению о перепроектировании, я принимаю его ответ как решение.

Спасибо за помощь.

1 Ответ

1 голос
/ 23 апреля 2019

Кажется, что вы делаете Преобразование правильно.Однако проблема заключается в вашем запросе 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"), чтобы запрос возвращалSparseArray внутри PlannerLine с идентификатором lineId.Вы должны изменить сигнатуру метода так, чтобы он принимал параметр lineId

@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); 

UPDATE

Если вы хотите получить List<PlannerLine> со всеми PlannerLine, хранящимися в базе данных, используйте следующий запрос в вашем Dao.

@Query("SELECT * FROM PlannerLine")
public List<PlannerLine> getAllPlannerLines(); 

Затем вы можете получить доступ к SparseArray изкаждая PlannerLine в списке, как обычно.

...