Skip to content

Instantly share code, notes, and snippets.

@seoft
Last active January 26, 2021 06:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save seoft/6c8eed9e3e1e533e6d30a44d8e842034 to your computer and use it in GitHub Desktop.
Save seoft/6c8eed9e3e1e533e6d30a44d8e842034 to your computer and use it in GitHub Desktop.
apply plugin: 'kotlin-kapt'
// ...(중략)...
dependencies {
// for async logic
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
// Room
implementation "androidx.room:room-runtime:2.2.2"
implementation "androidx.room:room-ktx:2.2.2"
kapt "androidx.room:room-compiler:2.2.2"
androidTestImplementation "androidx.room:room-testing:2.2.2"
implementation "androidx.room:room-rxjava2:2.2.2"
}
@Entity(tableName = "time_set")
data class TimeSet(
val title: String,
val times: List<Time>,
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "time_set_id")
val timeSetId: Int = 0
)
@Entity(
tableName = "time",
foreignKeys = [
ForeignKey(
entity = TimeSet::class,
parentColumns = ["time_set_id"],
childColumns = ["time_id"],
onDelete = CASCADE
)
]
)
data class Time(
val seconds: Int,
@Embedded
val bell: Bell,
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "time_id")
val timeId: Int = 0
)
@Entity(
tableName = "bell",
foreignKeys = [
ForeignKey(
entity = Time::class,
parentColumns = ["time_id"],
childColumns = ["bell_id"],
onDelete = CASCADE
)
]
)
data class Bell(
val bellType: BellType,
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "bell_id")
val bellId: Int = 0
) {
enum class BellType(type: Int) {
VIBRATE(0),
SLIENT(1),
NORMAL(2);
}
}
/**
* ref enum :
* https://stackoverflow.com/questions/51102431/android-room-type-convert-multiple-enum-types
*
* ref list field in room entity :
* https://medium.com/@toddcookevt/android-room-storing-lists-of-objects-766cca57e3f9
* https://stackoverflow.com/questions/49358773/android-room-cannot-recognize-typeconverer-for-list v
*/
class RoomConverter{
companion object {
val gson = Gson()
@JvmStatic
@TypeConverter
fun stringToTime(str:String?): List<Time> {
if(str.isNullOrEmpty()){
return emptyList()
}
return gson.fromJson<List<Time>>(str)
}
@JvmStatic
@TypeConverter
fun timeToString(times : List<Time>): String? {
if(times.isEmpty()){
return null
}
return gson.toJson(times)
}
}
@Suppress("NOTHING_TO_INLINE")
private inline fun <T : Enum<T>> T.toInt(): Int = this.ordinal
private inline fun <reified T : Enum<T>> Int.toEnum(): T = enumValues<T>()[this]
@TypeConverter
fun myEnumToTnt(value: Bell.BellType) = value.toInt()
@TypeConverter
fun intToMyEnum(value: Int) = value.toEnum<Bell.BellType>()
}
inline fun <reified T> Gson.fromJson(json: String) = this.fromJson<T>(json, object: TypeToken<T>() {}.type)
@Dao
interface TimeSetDao {
@Insert
fun insertUser(user: User)
@Query("SELECT * FROM user")
fun getUsers(): Single<List<User>>
@Query("SELECT * FROM user WHERE name=:name")
fun getUserByName(name: String): Single<User>
@Insert
fun insertTimeSet(time: TimeSet)
@Query("SELECT * FROM time_set")
fun getTimeSets(): Single<List<TimeSet>>
}
@Database(
entities = [
User::class,
Time::class,
TimeSet::class,
Bell::class
],
version = 1
)
@TypeConverters(RoomConverter::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun timeSetDao(): TimeSetDao
companion object {
private lateinit var INSTANCE: AppDatabase
var isUse = false
fun getDatabase(context: Context, testMode: Boolean = false): AppDatabase {
if (!isUse) {
isUse = true
synchronized(AppDatabase::class) {
INSTANCE = if (testMode) {
Room.inMemoryDatabaseBuilder(
context.applicationContext,
AppDatabase::class.java
).build()
} else {
Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java, "std-of-android.db"
).build()
}
}
}
return INSTANCE
}
}
}
fun insertUser(user: User) {
addDisposable(
Observable.just("")
.subscribeOn(Schedulers.io())
.doOnNext {
db.timeSetDao().insertUser(user)
}
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
mldSetResult.value = "done"
}, {
it.printStackTrace()
})
)
}
fun getUsers() {
addDisposable(
db.timeSetDao().getUsers()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
mldUsers.value = it
}, {
it.printStackTrace()
})
)
}
fun insertTimeSet(timeSet: TimeSet) {
addDisposable(
Observable.just("")
.subscribeOn(Schedulers.io())
.doOnNext {
db.timeSetDao().insertTimeSet(timeSet)
}
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
mldSetResult.value = "done"
}, {
it.printStackTrace()
})
)
}
fun getTimeSets() {
addDisposable(
db.timeSetDao().getTimeSets()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
mldTimeSets.value = it
}, {
it.printStackTrace()
})
)
}
@RunWith(AndroidJUnit4::class)
class RoomTest {
private lateinit var timeSetDao: TimeSetDao
private lateinit var db: AppDatabase
@JvmField
@Rule
val main = ActivityTestRule(MainActivity::class.java)
@Before
fun setUp() {
val context = main.activity
db = AppDatabase.getDatabase(context, true)
timeSetDao = db.timeSetDao()
}
@Test
fun UserTest() {
val user1 = User("AA", 10)
val user2 = User("BB", 20)
timeSetDao.insertUser(user1)
timeSetDao.insertUser(user2)
timeSetDao.getUserByName("AA").subscribe({
Assert.assertEquals("AA", it.name)
}, {
it.printStackTrace()
})
timeSetDao.getUsers().subscribe({
Assert.assertEquals(2, it.size)
}, {
it.printStackTrace()
})
}
@Test
fun TimeSetTest() {
val time1 = Time(1111, Bell(Bell.BellType.VIBRATE))
val time2 = Time(2222, Bell(Bell.BellType.SLIENT))
val time3 = Time(3333, Bell(Bell.BellType.VIBRATE))
val time4 = Time(4444, Bell(Bell.BellType.SLIENT))
val timeSet1 = TimeSet("TITLE 1", listOf(time1,time2))
val timeSet2 = TimeSet("TITLE 1", listOf(time3,time4))
timeSetDao.insertTimeSet(timeSet1)
timeSetDao.insertTimeSet(timeSet2)
timeSetDao.getTimeSets().subscribe({
it.e()
Assert.assertEquals(2 , it.size)
}, {
it.printStackTrace()
})
//////////// only exist time (don't have foreign relation) without timeSet
// val time1 = Time(1111, Bell(Bell.BellType.VIBRATE))
// val time2 = Time(2222, Bell(Bell.BellType.SLIENT))
// timeSetDao.insertTime(time1)
// timeSetDao.insertTime(time2)
// timeSetDao.getTimes().subscribe({
// it.e()
// Assert.assertEquals(2, it.size)
// }, {
// it.printStackTrace()
// })
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment