如何从房间数据库中的位置对象中保存和检索纬度和经度

Posted

技术标签:

【中文标题】如何从房间数据库中的位置对象中保存和检索纬度和经度【英文标题】:How to save and retrieve Latitude and Longitude from a Location object in Room Database 【发布时间】:2019-11-21 09:19:28 【问题描述】:

我正在为我的应用程序中的一个小型离线数据库使用 androidX Room 组件。我希望能够将用户的位置(纬度和经度)保存到数据库中,以便以后使用。 如何做到这一点以及最佳做法是什么?

我以前从未这样做过,在网上找不到任何帮助。

这就是我实际的做法(显然是错误的方式):

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

我收到一个错误 Cannot figure out how to save this field into database

【问题讨论】:

您可以将 Lat 和 Long 存储为单独的字符串 使用 TypeConverter 【参考方案1】:

您的Location 课程是什么?是android.location.Location 还是您定义的某个数据类?

在任何情况下,我都会使用@Embedded POJO 类而不是其他人推荐的TypeConverters

如果 Location 是您已经定义的类,则只需在 sessionLocation 顶部添加 @Embedded 注释

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

否则,如果Locationandroid.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

【讨论】:

我的 Location 类确实是 android.location.Location 类。感谢您的回复,但是由于我正在从事培训项目,因此我将使用类型转换器,因为我不熟悉它。以防万一,我会记住您的解决方案。 这是一种方式,但您必须定义您的自定义 Location 类,顺便说一下您的建议很有用【参考方案2】:

您应该为 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

【讨论】:

好的,非常感谢,我读过一些关于类型转换器的文章,但对 GSON 一无所知,这比只存储看起来有点野蛮的 long 和 lat 要好得多。我明天试试。 希望对您有所帮助,祝您好运! 我尝试使用 GSON 存储 Location 对象,但不幸的是它不起作用。只保存一个值。需要自定义 TypeConverter 吗? @Flyview,一句话:是的。 SQLite 可以存储位置等复杂数据,您必须定义自己的类型转换器才能将结构化类型转换为受支持的类型。更多信息:sqlite.org/datatype3.html

以上是关于如何从房间数据库中的位置对象中保存和检索纬度和经度的主要内容,如果未能解决你的问题,请参考以下文章

如何使用从服务中检索到的纬度和经度并在地图上显示它们?

如何从数据库中检索值

如何从 MySQL 中的 Multipolygon 中检索经纬度点

如何从我的 android 应用程序中尽快获得准确的纬度/经度?

如何将 ARKit SCNNode 对象位置 SCNVector3 转换为纬度和经度? [关闭]

如何从纬度/经度获取附近的位置?