Как сохранить и получить широту и долготу от объекта Location в базе данных комнат - PullRequest
0 голосов
/ 11 июля 2019

Я использую компонент AndroidX Room для небольшой автономной базы данных в моем приложении. Я хочу иметь возможность сохранить местоположение (широту и долготу) пользователя в базе данных и использовать его позже. Как это сделать и каковы лучшие практики?

Я никогда не делал этого раньше и не мог найти никакой помощи в Интернете.

Вот как я на самом деле это делаю (и, очевидно, неправильно):

@ColumnInfo(name = "session_location")
var sessionLocation: Location

Я получаю ошибку Cannot figure out how to save this field into database

Ответы [ 2 ]

1 голос
/ 12 июля 2019

Какой у вас класс Location? Это android.location.Location или какой-то класс данных, который вы определили?

В любом случае я бы использовал @Embedded классы POJO вместо TypeConverters, как рекомендуют другие.

Если Location - это класс, который вы уже определили, просто добавьте аннотацию @Embedded поверх вашего sessionLocation

@Embedded
@ColumnInfo(name = "session_location")
var sessionLocation: Location

Иначе, если Location - это android.location.Location, вам не нужно хранить всю информацию в этом классе. Вы должны нуждаться в основных, которые lat & long.

Я бы просто создал класс Location, сохранил бы эту основную информацию и добавил бы ее как @Embedded. Что-то вроде ниже

class Location {
    var latitude: Double = 0
    var longitude: Double = 0
}

class User {
    @Embedded
    @ColumnInfo(name = "session_location")
    var sessionLocation: Location
}

Как и предполагали другие, TypeConverter - это решение, но нет необходимости сериализовать / десериализовать POJO, когда вы можете просто сохранить его напрямую.

0 голосов
/ 11 июля 2019

Вы должны определить свой собственный конвертер для типов, которые не поддерживаются Room. В основном SQLite поддерживает только примитивные типы в качестве полей столбцов. Для каждого сложного типа данных вы должны определить пользовательский конвертер, так как Room не знает, как сериализовать ваш сложный тип в столбцах базы данных. Для этого вам нужно создать конвертер, который отвечает за преобразование вашего сложного структурированного типа в примитивные поля:

например. (из документации на андроид)

class Converters {
    @TypeConverter
    fun fromTimestamp(value: Long?): Date? {
        return value?.let { Date(it) }
    }

    @TypeConverter
    fun dateToTimestamp(date: Date?): Long? {
        return date?.time?.toLong()
    }
}

В вашем случае самым простым способом было бы использовать GSON для сериализации вашего объекта в виде строки JSON (когда вы пишете в свою базу данных - Room поддерживает строку), а затем анализировать строку из базы данных в вашу Location объект при чтении из базы

В вашем случае я бы сделал что-то вроде:

class LocationConverter {
   @TypeConverter
    fun toLocation(locationString: String?): Location? {
        return try {
            Gson().fromJson(locationString, Location::class.java)
        } catch (e: Exception) {
            null
        }
    }

    @TypeConverter
    fun toLocationString(location: Location?): String? {
        return Gson().toJson(location)
    }
}

Как только вы закончите с конвертером, аннотируйте вашу базу данных с помощью LocationConverter, который вы только что определили, и все готово!

@TypeConverters(LocationConverter::class)
abstract class YourDatabase : RoomDatabase() {
  // your code
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...