[Android] TypeConverter Annotation trong Room Database
Bài đăng này đã không được cập nhật trong 3 năm
Trong bài này mình sẽ hướng dẫn anh em setup @TypeConverter trong Room database
1. Room database là gì?
The Room persistence library provides an abstraction layer over SQLite to allow for more robust database access while harnessing the full power of SQLite.
Room là một persistence library, một phần của Android Architecture Components. Nó giúp bạn dễ dàng là việc với đối tượng SQLiteDatabase trong ứng dụng của bạn hơn, giảm số lượng mã soạn sẵn và xác minh các truy vấn SQL tại thời điểm biên dịch.
Trước khi Room được ra mắt, chúng ta phải viết rất nhiều dòng lệnh phức tạp, dài loằng ngoằng, cơ bản là rất tốn thời gian để setup SQLite . Room xuất hiện như một vị cứu tinh giúp đỡ anh em, từng câu lệnh, từng query cực kì đơn giản và dễ hiểu. Room cung cấp rất nhiều function, hỗ trợ lưu trữ các dữ liệu nguyên thủy nhưng nó không hỗ trợ các Class Object cho người dùng tự định nghĩa. Tuy nhiên các bạn không phải lo lắng về điều này. TypeConverter lại xuất hiện để cứu anh em. TypeConverter có thể convert một Custom Class sang kiểu dữ liệu mà Room có thể lưu trữ được và ngược lại.
2. Cài đặt
@Entity(tableName = "current_weather")
data class CurrentWeatherResponse(
val coord: Coord,
@PrimaryKey
val id: Int,
val main: Main,
val name: String,
val sys: Sys,
val visibility: Int,
val weather: List<Weather>,
val wind: Wind
): Serializable
Đây là một Entity của Database tuy nhiên, Entity này có những property không phải dữ liệu nguyên thủy như: Coord, Main, Sys, List<Weather>, Wind. Sau đây chúng ta sẽ bắt tay vào định nghĩa lớp Converters để convert các propery này nhé:
class Converters {
@TypeConverter
fun toCoord(coord: String): Coord? {
return Gson().fromJson<Coord>(coord,Coord::class.java)
}
@TypeConverter
fun fromCoord(coord: Coord): String? {
return Gson().toJson(coord)
}
@TypeConverter
fun toWind(wind: String): Wind? {
return Gson().fromJson<Wind>(wind,Wind::class.java)
}
@TypeConverter
fun fromWind(wind: Wind): String? {
return Gson().toJson(wind)
}
@TypeConverter
fun toMain(main: String): Main? {
return Gson().fromJson<Main>(main,Main::class.java)
}
@TypeConverter
fun fromMain(main: Main): String? {
return Gson().toJson(main)
}
@TypeConverter
fun toSys(sys: String): Sys? {
return Gson().fromJson<Sys>(sys,Sys::class.java)
}
@TypeConverter
fun fromSys(sys: Sys): String? {
return Gson().toJson(sys)
}
@TypeConverter
fun toWeather(weather: String): List<Weather>? {
val listType = object : TypeToken<ArrayList<Weather>>(){}.type
return Gson().fromJson<List<Weather>>(weather,listType)
}
@TypeConverter
fun fromWeather(weather: List<Weather>): String? {
return Gson().toJson(weather)
}
}
Như mình đã đề cập, Room chỉ lưu trữ các kiểu dữ liệu nguyên thủy nên giải pháp ở đây là convert Object -> dữ liệu nguyên thủy. Và mình sử dụng Gson để convert Object -> String. Bạn phải tạo 2 function để convert qua lại: Object -> String và String -> Object (như mình đã tạo là to... & from...) Đừng quên Anotation @TypeConverter trên mỗi function nhé.
3. Kết thúc
@Database(
entities = [CurrentWeatherResponse::class],
version = 1,
exportSchema = false
)
@TypeConverters(Converters::class)
abstract class WeatherDatabase : RoomDatabase() {
abstract fun getWeatherDao(): WeatherDao
companion object{
@Volatile
private var instance: WeatherDatabase?=null
private val LOCK = Any()
operator fun invoke(context: Context) = instance?: synchronized(LOCK){
instance?: createDatabase(context).also{
instance = it
}
}
private fun createDatabase(context: Context) =
Room.databaseBuilder(
context.applicationContext,
WeatherDatabase::class.java,
"weather.db"
).build()
}
}
Bước cuối cùng là thêm Anotation @TypeConverters(Converters::class) ở abstract class Database nữa nhé. Vậy là bạn đã setup TypeConverter vào dự án của bạn thành công.
Code được lấy trong project:
All rights reserved