Commit fdc869bb authored by Joey's avatar Joey

data: update room to 2.1.0-beta01

Mark all UI-blocking operations suspend
Signed-off-by: Joey's avatarJoey <bevilacquajoey@gmail.com>
Change-Id: Id7107e5cd1bb127dd5fb2450117930a9b7451db6
parent bf7c4e73
......@@ -11,10 +11,10 @@ package it.diab.viewmodels.glucose
import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.test.core.app.ApplicationProvider
import it.diab.data.AppDatabase
import it.diab.data.extensions.insulin
import it.diab.data.repositories.GlucoseRepository
import it.diab.data.repositories.InsulinRepository
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
......@@ -27,13 +27,15 @@ class GlucoseListViewModelTest {
val rule = InstantTaskExecutorRule()
@Before
fun setup() {
AppDatabase.TEST_MODE = true
fun setup() = runBlocking {
val context = ApplicationProvider.getApplicationContext<Context>()
// Insert test data
AppDatabase.getInstance(context).insulin()
.insert(*TEST_DATA)
InsulinRepository.getInstance(context).apply {
setDebugMode()
insert(TEST_DATA[0])
insert(TEST_DATA[1])
}
viewModel = GlucoseListViewModel(
GlucoseRepository.getInstance(context),
......
......@@ -11,7 +11,6 @@ package it.diab.viewmodels.glucose
import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.test.core.app.ApplicationProvider
import it.diab.data.AppDatabase
import it.diab.data.entities.TimeFrame
import it.diab.data.repositories.GlucoseRepository
import it.diab.data.extensions.glucose
......@@ -40,10 +39,12 @@ class OverviewViewModelTest {
@Before
fun setup() {
AppDatabase.TEST_MODE = true
val context = ApplicationProvider.getApplicationContext<Context>()
viewModel = OverviewViewModel(GlucoseRepository.getInstance(context))
val repo = GlucoseRepository.getInstance(context).apply {
setDebugMode()
}
viewModel = OverviewViewModel(repo)
}
@Test
......
......@@ -36,7 +36,7 @@ class GlucoseListViewModel internal constructor(
fun getInsulin(uid: Long) = insulins.firstOrNull { it.uid == uid } ?: Insulin()
@VisibleForTesting
fun runPrepare() {
suspend fun runPrepare() {
insulins = insulinRepository.getInsulins()
}
}
\ No newline at end of file
......@@ -34,8 +34,9 @@ android {
dependencies {
implementation project(':core')
api "androidx.room:room-runtime:2.0.0"
kapt "androidx.room:room-compiler:2.0.0"
implementation "androidx.room:room-ktx:2.1.0-beta01"
implementation "androidx.room:room-runtime:2.1.0-beta01"
kapt "androidx.room:room-compiler:2.1.0-beta01"
api "androidx.paging:paging-runtime:2.1.0"
}
......
......@@ -17,6 +17,7 @@ import it.diab.data.entities.TimeFrame
import it.diab.data.extensions.glucose
import it.diab.data.extensions.insulin
import junit.framework.Assert.assertEquals
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Test
......@@ -34,7 +35,7 @@ class AppDatabaseTest {
}
@Test
fun addGlucose() {
fun addGlucose() = runBlocking {
val item = glucose {
uid = 1
value = 100
......@@ -48,7 +49,7 @@ class AppDatabaseTest {
}
@Test
fun addInsulin() {
fun addInsulin() = runBlocking {
val item = insulin {
uid = 1
name = "TEST 0"
......@@ -61,7 +62,7 @@ class AppDatabaseTest {
}
@Test
fun addGlucoseWithLinkedInsulins() {
fun addGlucoseWithLinkedInsulins() = runBlocking {
val insulin = insulin {
uid = 2
name = "TEST 1"
......
......@@ -58,5 +58,5 @@ class Hba1cRepositoryTest {
assertNotEquals(item.uid, repository.getById(item.uid))
}
private fun Hba1cRepository.getById(uid: Long) = getAllItems().firstOrNull { it.uid == uid }
private suspend fun Hba1cRepository.getById(uid: Long) = getAllItems().firstOrNull { it.uid == uid }
}
\ No newline at end of file
......@@ -33,17 +33,17 @@ interface GlucoseDao {
val last: LiveData<List<Glucose>>
@Query("SELECT * FROM glucose WHERE uid IN (:uids)")
fun getById(vararg uids: Long): List<Glucose>
suspend fun getById(vararg uids: Long): List<Glucose>
@Query("SELECT * FROM glucose ORDER BY date DESC")
fun getAllItems(): List<Glucose>
suspend fun getAllItems(): List<Glucose>
@Query("SELECT * FROM glucose WHERE date >= :minTime AND date <= :maxTime ORDER BY date DESC")
fun getInDateRange(minTime: Long, maxTime: Long): List<Glucose>
suspend fun getInDateRange(minTime: Long, maxTime: Long): List<Glucose>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg glucose: Glucose)
suspend fun insert(vararg glucose: Glucose)
@Delete
fun delete(glucose: Glucose)
suspend fun delete(glucose: Glucose)
}
......@@ -26,11 +26,11 @@ interface Hba1cDao {
val all: LiveData<List<Hba1c>>
@Query("SELECT * FROM hba1c ORDER BY date DESC")
fun getAllItems(): List<Hba1c>
suspend fun getAllItems(): List<Hba1c>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg items: Hba1c)
suspend fun insert(vararg items: Hba1c)
@Delete
fun delete(item: Hba1c)
suspend fun delete(item: Hba1c)
}
\ No newline at end of file
......@@ -26,17 +26,17 @@ interface InsulinDao {
val all: DataSource.Factory<Int, Insulin>
@Query("SELECT * FROM insulin")
fun getInsulins(): List<Insulin>
suspend fun getInsulins(): List<Insulin>
@Query("SELECT * FROM insulin WHERE isBasal = 1")
fun getBasals(): List<Insulin>
suspend fun getBasals(): List<Insulin>
@Query("SELECT * FROM insulin WHERE uid IN (:uids)")
fun getById(vararg uids: Long): List<Insulin>
suspend fun getById(vararg uids: Long): List<Insulin>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg insulins: Insulin): Array<Long>
suspend fun insert(vararg insulins: Insulin): Array<Long>
@Delete
fun delete(insulin: Insulin)
suspend fun delete(insulin: Insulin)
}
/*
* Copyright (c) 2019 Bevilacqua Joey
*
* Licensed under the GNU GPLv3 license
*
* The text of the license can be found in the LICENSE file
* or at https://www.gnu.org/licenses/gpl.txt
*/
package it.diab.data.repositories
import androidx.annotation.VisibleForTesting
import it.diab.data.AppDatabase
abstract class BaseRepository {
@VisibleForTesting
fun setDebugMode() {
AppDatabase.TEST_MODE = true
}
}
\ No newline at end of file
......@@ -9,7 +9,6 @@
package it.diab.data.repositories
import android.content.Context
import androidx.annotation.WorkerThread
import it.diab.core.util.SingletonHolder
import it.diab.data.AppDatabase
import it.diab.data.dao.GlucoseDao
......@@ -17,7 +16,7 @@ import it.diab.data.entities.Glucose
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.withContext
class GlucoseRepository private constructor(private val dao: GlucoseDao) {
class GlucoseRepository private constructor(private val dao: GlucoseDao) : BaseRepository() {
val all = dao.all
......@@ -25,19 +24,25 @@ class GlucoseRepository private constructor(private val dao: GlucoseDao) {
val last = dao.last
@WorkerThread
fun getById(uid: Long) = dao.getById(uid).firstOrNull() ?: Glucose()
suspend fun getById(uid: Long) = withContext(IO) {
dao.getById(uid).firstOrNull() ?: Glucose()
}
@WorkerThread
fun getAllItems() = dao.getAllItems()
suspend fun getAllItems() = withContext(IO) {
dao.getAllItems()
}
@WorkerThread
fun getInDateRange(minTime: Long, maxTime: Long) =
suspend fun getInDateRange(minTime: Long, maxTime: Long) = withContext(IO) {
dao.getInDateRange(minTime, maxTime)
}
suspend fun insert(glucose: Glucose) = withContext(IO) { dao.insert(glucose) }
suspend fun insert(glucose: Glucose) = withContext(IO) {
dao.insert(glucose)
}
suspend fun delete(glucose: Glucose) = withContext(IO) { dao.delete(glucose) }
suspend fun delete(glucose: Glucose) = withContext(IO) {
dao.delete(glucose)
}
companion object : SingletonHolder<GlucoseRepository, Context>({
GlucoseRepository(AppDatabase.getInstance(it).glucose())
......
......@@ -9,7 +9,6 @@
package it.diab.data.repositories
import android.content.Context
import androidx.annotation.WorkerThread
import it.diab.core.util.SingletonHolder
import it.diab.data.AppDatabase
import it.diab.data.dao.Hba1cDao
......@@ -17,16 +16,21 @@ import it.diab.data.entities.Hba1c
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.withContext
class Hba1cRepository private constructor(private val hba1cDao: Hba1cDao) {
class Hba1cRepository private constructor(private val hba1cDao: Hba1cDao) : BaseRepository() {
val all = hba1cDao.all
@WorkerThread
fun getAllItems() = hba1cDao.getAllItems()
suspend fun getAllItems() = withContext(IO) {
hba1cDao.getAllItems()
}
suspend fun insert(item: Hba1c) = withContext(IO) { hba1cDao.insert(item) }
suspend fun insert(item: Hba1c) = withContext(IO) {
hba1cDao.insert(item)
}
suspend fun delete(item: Hba1c) = withContext(IO) { hba1cDao.delete(item) }
suspend fun delete(item: Hba1c) = withContext(IO) {
hba1cDao.delete(item)
}
companion object : SingletonHolder<Hba1cRepository, Context>({
Hba1cRepository(AppDatabase.getInstance(it).hba1c())
......
......@@ -9,30 +9,36 @@
package it.diab.data.repositories
import android.content.Context
import androidx.annotation.WorkerThread
import it.diab.data.dao.InsulinDao
import it.diab.data.entities.Insulin
import it.diab.core.util.SingletonHolder
import it.diab.data.AppDatabase
import it.diab.data.dao.InsulinDao
import it.diab.data.entities.Insulin
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.withContext
class InsulinRepository private constructor(private val dao: InsulinDao) {
class InsulinRepository private constructor(private val dao: InsulinDao) : BaseRepository() {
val all = dao.all
@WorkerThread
fun getInsulins() = dao.getInsulins()
suspend fun getInsulins() = withContext(IO) {
dao.getInsulins()
}
@WorkerThread
fun getBasals() = dao.getBasals()
suspend fun getBasals() = withContext(IO) {
dao.getBasals()
}
@WorkerThread
fun getById(uid: Long) = dao.getById(uid).firstOrNull() ?: Insulin()
suspend fun getById(uid: Long) = withContext(IO) {
dao.getById(uid).firstOrNull() ?: Insulin()
}
suspend fun insert(insulin: Insulin) = withContext(IO) { dao.insert(insulin) }
suspend fun insert(insulin: Insulin) = withContext(IO) {
dao.insert(insulin)
}
suspend fun delete(insulin: Insulin) = withContext(IO) { dao.delete(insulin) }
suspend fun delete(insulin: Insulin) = withContext(IO) {
dao.delete(insulin)
}
companion object : SingletonHolder<InsulinRepository, Context>({
InsulinRepository(AppDatabase.getInstance(it).insulin())
......
......@@ -33,7 +33,7 @@ class GlucoseTest {
}
@Test
fun equals() {
fun comparison() {
val a = glucose {
uid = 1
value = 100
......
......@@ -26,7 +26,7 @@ class Hba1cTest {
}
@Test
fun equals() {
fun comparison() {
val a = hba1c {
uid = 1
value = 10f
......
......@@ -45,7 +45,7 @@ class InsulinTest {
}
@Test
fun equals() {
fun comparison() {
val a = insulin {
uid = 1
name = "test"
......
......@@ -36,7 +36,7 @@ class ExportService : Service() {
private lateinit var outUri: Uri
private val job = Job()
private val serviceScope = CoroutineScope(Dispatchers.IO + job)
private val serviceScope = CoroutineScope(Dispatchers.Default + job)
override fun onCreate() {
super.onCreate()
......
......@@ -25,7 +25,7 @@ class MlWriter(
private val filterRange: IntRange
) {
fun export(): Boolean {
suspend fun export(): Boolean {
val end = System.currentTimeMillis()
val start = end - DAYS_TO_EXPORT
......@@ -45,7 +45,7 @@ class MlWriter(
}
}
private fun exportTrain(
private suspend fun exportTrain(
zipStream: ZipOutputStream,
timeFrame: TimeFrame,
start: Long,
......@@ -68,7 +68,7 @@ class MlWriter(
// DON'T CLOSE THE STREAM HERE
}
private fun exportTest(
private suspend fun exportTest(
zipStream: ZipOutputStream,
targetTimeFrame: TimeFrame,
nextTimeFrame: TimeFrame,
......
......@@ -11,9 +11,9 @@ package it.diab.export.writer
import android.os.Build
import android.os.ParcelFileDescriptor
import android.util.Log
import androidx.annotation.WorkerThread
import it.diab.core.util.extensions.forEachWithIndex
import it.diab.core.util.extensions.format
import it.diab.data.entities.Glucose
import it.diab.data.repositories.GlucoseRepository
import it.diab.data.repositories.InsulinRepository
import it.diab.export.BuildConfig
......@@ -65,8 +65,7 @@ class XlsxWriter(
}
}
@WorkerThread
private fun buildGlucoseSheet(
private suspend fun buildGlucoseSheet(
sheet: Worksheet,
glucoseRepository: GlucoseRepository,
insulinRepository: InsulinRepository,
......@@ -76,34 +75,13 @@ class XlsxWriter(
sheet.style(0, headers.size - 1).bold()
val list = glucoseRepository.getAllItems()
list.forEachWithIndex { i, glucose ->
sheet.apply {
val insulin = insulinRepository.getById(glucose.insulinId0)
val basal = insulinRepository.getById(glucose.insulinId1)
val row = i + 1
write(
glucose.value to (row to 0),
// Java 8's java.time.LocalDateTime is required for this
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) glucose.date to (row to 1)
else glucose.date.format(DATE_FORMAT) to (row to 1),
glucose.eatLevel to (row to 2)
)
if (insulin.name.isNotEmpty()) {
write(
insulin.name to (row to 3),
glucose.insulinValue0 to (row to 4)
)
}
if (basal.name.isNotEmpty()) {
write(
basal.name to (row to 5),
glucose.insulinValue1 to (row to 6)
)
}
}
// Kotlin goes mad if we write a suspend function inside a forEachIndexed code block
var i = 0
while (i < list.size) {
val glucose = list[i]
writeGlucoseRow(sheet, insulinRepository, glucose, i)
i++
}
sheet.setAlternateBackground(list.size, headers.size - 1)
......@@ -117,8 +95,43 @@ class XlsxWriter(
}
}
@WorkerThread
private fun buildInsulinSheet(
private suspend fun writeGlucoseRow(
sheet: Worksheet,
insulinRepository: InsulinRepository,
glucose: Glucose,
position: Int
) {
val insulin = insulinRepository.getById(glucose.insulinId0)
val basal = insulinRepository.getById(glucose.insulinId1)
sheet.apply {
val row = position + 1
write(
glucose.value to (row to 0),
// Java 8's java.time.LocalDateTime is required for this
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) glucose.date to (row to 1)
else glucose.date.format(DATE_FORMAT) to (row to 1),
glucose.eatLevel to (row to 2)
)
if (insulin.name.isNotEmpty()) {
write(
insulin.name to (row to 3),
glucose.insulinValue0 to (row to 4)
)
}
if (basal.name.isNotEmpty()) {
write(
basal.name to (row to 5),
glucose.insulinValue1 to (row to 6)
)
}
}
}
private suspend fun buildInsulinSheet(
sheet: Worksheet,
insulinRepository: InsulinRepository,
headers: List<String>
......
......@@ -11,7 +11,6 @@ package it.diab.glucose.viewmodels
import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.test.core.app.ApplicationProvider
import it.diab.data.AppDatabase
import it.diab.data.entities.Glucose
import it.diab.data.entities.TimeFrame
import it.diab.data.repositories.GlucoseRepository
......@@ -30,7 +29,7 @@ import org.junit.Test
class EditorViewModelTest {
private lateinit var db: AppDatabase
private lateinit var glucoseRepo: GlucoseRepository
private lateinit var viewModel: EditorViewModel
private lateinit var pluginManager: PluginManager
......@@ -57,19 +56,27 @@ class EditorViewModelTest {
}
@Before
fun setup() {
AppDatabase.TEST_MODE = true
fun setup() = runBlocking {
val context = ApplicationProvider.getApplicationContext<Context>()
db = AppDatabase.getInstance(context)
viewModel = EditorViewModel(
GlucoseRepository.getInstance(context),
InsulinRepository.getInstance(context)
)
pluginManager = PluginManager(context)
db.glucose().insert(testGlucose)
db.insulin().insert(testInsulin, testBasal)
glucoseRepo = GlucoseRepository.getInstance(context).apply {
setDebugMode()
insert(testGlucose)
}
InsulinRepository.getInstance(context).apply {
setDebugMode()
insert(testInsulin)
insert(testBasal)
}
// setup is required to be "void"
Unit
}
@Test
......@@ -85,7 +92,7 @@ class EditorViewModelTest {
fun save() = runBlocking {
viewModel.runSetGlucose(-1)
val initialSize = db.glucose().getInDateRange(0, System.currentTimeMillis()).size
val initialSize = glucoseRepo.getInDateRange(0, System.currentTimeMillis()).size
viewModel.glucose.apply {
value = 81
......@@ -98,7 +105,7 @@ class EditorViewModelTest {
delay(500)
val finalSize = db.glucose().getInDateRange(0, System.currentTimeMillis()).size
val finalSize = glucoseRepo.getInDateRange(0, System.currentTimeMillis()).size
assertTrue(finalSize > initialSize)
}
......
......@@ -9,12 +9,12 @@
package it.diab.glucose.viewmodels
import androidx.annotation.VisibleForTesting
import it.diab.core.viewmodels.ScopedViewModel
import it.diab.data.entities.Glucose
import it.diab.data.entities.Insulin
import it.diab.data.plugin.PluginManager
import it.diab.data.repositories.GlucoseRepository
import it.diab.data.repositories.InsulinRepository
import it.diab.data.plugin.PluginManager
import it.diab.core.viewmodels.ScopedViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
......@@ -99,7 +99,7 @@ class EditorViewModel internal constructor(
}
@VisibleForTesting
fun runSetGlucose(uid: Long) {
suspend fun runSetGlucose(uid: Long) {
glucose = glucoseRepository.getById(uid)
}
......
......@@ -38,7 +38,7 @@ class EditorViewModel internal constructor(
}
@VisibleForTesting
fun runSetInsulin(uid: Long): Insulin {
suspend fun runSetInsulin(uid: Long): Insulin {
return insulinRepository.getById(uid)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment