如何从房间数据库中的位置对象保存和检索纬度和经度
How to save and retrieve Latitude and Longitude from a Location object in Room Database
我在我的应用程序中将 AndroidX Room 组件用于小型离线数据库。我希望能够将用户的位置(纬度和经度)保存到数据库中,供以后使用。
如何去做以及最佳做法是什么?
我以前从未这样做过,在网上找不到任何帮助。
这就是我实际做的方式(显然是错误的方式):
@ColumnInfo(name = "session_location")
var sessionLocation: Location
我得到一个错误 Cannot figure out how to save this field into database
您应该为 Room 不支持的类型定义自己的转换器。基本上 SQLite 只支持原始类型作为列字段。
对于每种复杂数据类型,您必须定义一个自定义转换器,因为 Room 不知道如何在数据库列中序列化您的复杂类型。
为此,您需要创建一个转换器,负责转换原始字段中的复杂结构类型:
例如(来自 android 文档)
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
}
你的 Location
class 是什么?是android.location.Location
还是你定义的一些数据class?
在任何情况下,我都会使用 @Embedded
POJO classes 而不是其他人推荐的 TypeConverters
。
如果 Location
是您已经定义的 class 则只需在您的 sessionLocation
之上添加 @Embedded
注释
@Embedded
@ColumnInfo(name = "session_location")
var sessionLocation: Location
否则,如果 Location
是 android.location.Location
,则您不需要将所有信息存储在 class 中。您必须需要基本的 lat & long
。
我会创建一个 class Location
并存储这些基本信息并将其添加为 @Embedded
。如下所示
class Location {
var latitude: Double = 0
var longitude: Double = 0
}
class User {
@Embedded
@ColumnInfo(name = "session_location")
var sessionLocation: Location
}
正如其他人所建议的那样,TypeConverter
是一种解决方案,但不需要 serialize/deserialize 和 POJO
,只要直接保存即可。
我在我的应用程序中将 AndroidX Room 组件用于小型离线数据库。我希望能够将用户的位置(纬度和经度)保存到数据库中,供以后使用。 如何去做以及最佳做法是什么?
我以前从未这样做过,在网上找不到任何帮助。
这就是我实际做的方式(显然是错误的方式):
@ColumnInfo(name = "session_location")
var sessionLocation: Location
我得到一个错误 Cannot figure out how to save this field into database
您应该为 Room 不支持的类型定义自己的转换器。基本上 SQLite 只支持原始类型作为列字段。 对于每种复杂数据类型,您必须定义一个自定义转换器,因为 Room 不知道如何在数据库列中序列化您的复杂类型。 为此,您需要创建一个转换器,负责转换原始字段中的复杂结构类型:
例如(来自 android 文档)
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
}
你的 Location
class 是什么?是android.location.Location
还是你定义的一些数据class?
在任何情况下,我都会使用 @Embedded
POJO classes 而不是其他人推荐的 TypeConverters
。
如果 Location
是您已经定义的 class 则只需在您的 sessionLocation
@Embedded
注释
@Embedded
@ColumnInfo(name = "session_location")
var sessionLocation: Location
否则,如果 Location
是 android.location.Location
,则您不需要将所有信息存储在 class 中。您必须需要基本的 lat & long
。
我会创建一个 class Location
并存储这些基本信息并将其添加为 @Embedded
。如下所示
class Location {
var latitude: Double = 0
var longitude: Double = 0
}
class User {
@Embedded
@ColumnInfo(name = "session_location")
var sessionLocation: Location
}
正如其他人所建议的那样,TypeConverter
是一种解决方案,但不需要 serialize/deserialize 和 POJO
,只要直接保存即可。