База данных Android для Android: как обрабатывать Arraylist в сущности?
Я только что внедрил Room для автономной экономии данных. Но в классе Entity я получаю следующую ошибку:
Error:(27, 30) error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
И класс следующий:
@Entity(tableName = "firstPageData")
public class MainActivityData {
@PrimaryKey
private String userId;
@ColumnInfo(name = "item1_id")
private String itemOneId;
@ColumnInfo(name = "item2_id")
private String itemTwoId;
// THIS IS CAUSING THE ERROR... BASICALLY IT ISN'T READING ARRAYS
@ColumnInfo(name = "mylist_array")
private ArrayList<MyListItems> myListItems;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public ArrayList<MyListItems> getMyListItems() {
return myListItems;
}
public void setCheckListItems(ArrayList<MyListItems> myListItems) {
this.myListItems = myListItems;
}
}
Итак, в основном я хочу сохранить ArrayList в базе данных, но я не смог найти что-либо, относящееся к нему. Можете ли вы посоветовать мне, как сохранить массив с помощью комнаты?
ПРИМЕЧАНИЕ. Класс MyListItems Pojo содержит 2 строки (на данный момент)
Спасибо заранее.
Ответы
Ответ 1
Вариант №1: MyListItems
должен быть @Entity
, как MainActivityData
. MyListItems
установит @ForeignKey
обратно на MainActivityData
. В этом случае, однако, MainActivityData
не может иметь private ArrayList<MyListItems> myListItems
, как в комнате, объекты не относятся к другим объектам. Модель просмотра или аналогичная конструкция POJO может иметь MainActivityData
и связанный с ней ArrayList<MyListItems>
.
Вариант №2: Настройте пару методов @TypeConverter
для преобразования ArrayList<MyListItems>
в и из некоторого базового типа (например, a String
, например, используя JSON в качестве формата хранения). Теперь MainActivityData
может иметь свой ArrayList<MyListItems>
напрямую. Однако для MyListItems
не будет отдельной таблицы, поэтому вы не можете запросить на MyListItems
очень хорошо.
Ответ 2
Тип Converter специально для этого. В вашем случае вы можете использовать приведенный ниже фрагмент кода для хранения данных в БД.
public class Converters {
@TypeConverter
public static ArrayList<String> fromString(String value) {
Type listType = new TypeToken<ArrayList<String>>() {}.getType();
return new Gson().fromJson(value, listType);
}
@TypeConverter
public static String fromArrayList(ArrayList<String> list) {
Gson gson = new Gson();
String json = gson.toJson(list);
return json;
}
}
И упоминаем этот класс в вашей комнате DB, как это
@Database (entities = {MainActivityData.class},version = 1)
@TypeConverters({Converters.class})
Подробнее здесь
Ответ 3
Версия Kotlin для преобразователя типов:
class Converters {
@TypeConverter
fun listToJson(value: List<JobWorkHistory>?): String {
return Gson().toJson(value)
}
@TypeConverter
fun jsonToList(value: String): List<JobWorkHistory>? {
val objects = Gson().fromJson(value, Array<JobWorkHistory>::class.java) as Array<JobWorkHistory>
val list = objects.toList()
return list
}
}
Я использовал объект JobWorkHistory
для своих целей, используйте свой собственный объект
@Database(entities = arrayOf(JobDetailFile::class, JobResponse::class), version = 1)
@TypeConverters(Converters::class)
abstract class MyRoomDataBase : RoomDatabase() {
abstract fun attachmentsDao(): AttachmentsDao
}
Ответ 4
Вот как я справляюсь с преобразованием списка
public class GenreConverter {
@TypeConverter
public List<Integer> gettingListFromString(String genreIds) {
List<Integer> list = new ArrayList<>();
String[] array = genreIds.split(",");
for (String s : array) {
if (!s.isEmpty()) {
list.add(Integer.parseInt(s));
}
}
return list;
}
@TypeConverter
public String writingStringFromList(List<Integer> list) {
String genreIds = "";
for (int i : list) {
genreIds += "," + i;
}
return genreIds;
}}
А затем в базе данных я делаю, как показано ниже
@Database(entities = {MovieEntry.class}, version = 1)
@TypeConverters(GenreConverter.class)
А ниже приведена одна и та же реализация kotlin;
class GenreConverter {
@TypeConverter
fun gettingListFromString(genreIds: String): List<Int> {
val list = mutableListOf<Int>()
val array = genreIds.split(",".toRegex()).dropLastWhile {
it.isEmpty()
}.toTypedArray()
for (s in array) {
if (s.isNotEmpty()) {
list.add(s.toInt())
}
}
return list
}
@TypeConverter
fun writingStringFromList(list: List<Int>): String {
var genreIds=""
for (i in list) genreIds += ",$i"
return genreIds
}}
Ответ 5
Имело такое же сообщение об ошибке, как описано выше.
Я хотел бы добавить: если вы получите это сообщение об ошибке в @Query, вы должны добавить @TypeConverters над аннотацией @Query.
Пример:
@TypeConverters(DateConverter.class)
@Query("update myTable set myDate=:myDate where id = :myId")
void updateStats(int myId, Date myDate);
....
public class DateConverter {
@TypeConverter
public static Date toDate(Long timestamp) {
return timestamp == null ? null : new Date(timestamp);
}
@TypeConverter
public static Long toTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
Ответ 6
Лучшая версия конвертера List<String>
class StringListConverter {
@TypeConverter
fun fromString(stringListString: String): List<String> {
return stringListString.split(",").map { it }
}
@TypeConverter
fun toString(stringList: List<String>): String {
return stringList.joinToString(separator = ",")
}
}
Ответ 7
Этот ответ использует Kotin для разделения через запятую и построения строки, разделенной запятой. Запятая должна идти в конце всех элементов, кроме последнего, поэтому она будет обрабатывать и списки отдельных элементов.
object StringListConverter {
@TypeConverter
@JvmStatic
fun toList(strings: String): List<String> {
val list = mutableListOf<String>()
val array = strings.split(",")
for (s in array) {
list.add(s)
}
return list
}
@TypeConverter
@JvmStatic
fun toString(strings: List<String>): String {
var result = ""
strings.forEachIndexed { index, element ->
result += element
if(index != (strings.size-1)){
result += ","
}
}
return result
}
}
Ответ 8
Добавление @TypeConverters
с классом конвертера в качестве параметров
к базе данных и к классу Дао, заставил мои запросы работать
Ответ 9
Преобразования Json плохо масштабируются с точки зрения распределения памяти. Я бы предпочел что-то похожее на ответы выше с некоторой обнуляемостью.
class Converters {
@TypeConverter
fun stringAsStringList(strings: String?): List<String> {
val list = mutableListOf<String>()
strings
?.split(",")
?.forEach {
list.add(it)
}
return list
}
@TypeConverter
fun stringListAsString(strings: List<String>?): String {
var result = ""
strings?.forEach { element ->
result += "$element,"
}
return result.removeSuffix(",")
}
}
Для простых типов данных можно использовать вышеуказанное, в противном случае для сложных типов данных Room предоставляет Embedded
Ответ 10
Используйте официальное решение из комнаты, @Встроенная аннотация:
@Embedded(prefix = "mylist_array") private ArrayList<MyListItems> myListItems