I'm using AndroidX Room component for a small offline database in my app. I want to be able to save the Location (latitude and longitude) of the user to the database and use it later. How to do it and what is the best practices ?
I've never done that before and couldn't find any help on the web.
This is how I'm actually doing it (and obviously the wrong way) :
@ColumnInfo(name = "session_location")
var sessionLocation: Location
I get an error Cannot figure out how to save this field into database
What is your Location
class? Is it android.location.Location
or is it some data class that you defined?
In any case I would have used @Embedded
POJO classes instead of TypeConverters
as others recommend.
If Location
is a class that you already defined then just add @Embedded
annotation on top of your sessionLocation
@Embedded
@ColumnInfo(name = "session_location")
var sessionLocation: Location
Else if Location
is the android.location.Location
then you don't need to store all the information in that class. You must need basic ones which are lat & long
.
I would have just created a class Location
and store those basic information and add it as @Embedded
. Something like below
class Location {
var latitude: Double = 0
var longitude: Double = 0
}
class User {
@Embedded
@ColumnInfo(name = "session_location")
var sessionLocation: Location
}
As others suggested TypeConverter
is a solution but there is no need serialize/deserialize a POJO
when you can simply save it directly.
You should define your own converter for types that are not supported by Room. Basically SQLite supports only primitive types as column fields. For each complex data type you have to define a custom converter, since Room doesn't know how to serialize your complex type in database columns. To do so, you need to create a converter which is responsible to convert your complex structured type in primitive fields:
E.g. (from android documentation)
class Converters {
@TypeConverter
fun fromTimestamp(value: Long?): Date? {
return value?.let { Date(it) }
}
@TypeConverter
fun dateToTimestamp(date: Date?): Long? {
return date?.time?.toLong()
}
}
In your case the simpliest way would be using GSON to serialize your object as a JSON string (when you are writing to your database - Room supports string), then parsing the string from the database to your Location
object when you read from the database
In your case I would do something like:
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)
}
}
Once your done with the converter, annotate your database with the LocationConverter
you've just defined and you're done!
@TypeConverters(LocationConverter::class)
abstract class YourDatabase : RoomDatabase() {
// your code
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With