Last active
January 26, 2021 06:43
-
-
Save seoft/6c8eed9e3e1e533e6d30a44d8e842034 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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>> | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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 | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
}) | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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