技术分享 在 Android 中使用 Room 从 SQlite 数据库中获取实体列表的正确方法是什么?

kakax · 2023年10月24日 · 79 次阅读

这是 AmamResourceDao. kt 文件的内容:

@Daointerface AlarmResourceDao {

    @Query(
        value = """
            SELECT * FROM alarm_resources
            WHERE
                is_scheduled = 'T'
            ORDER BY id ASC
        """
    )fun getAllScheduledAlarmResources(): Flow<List<AlarmResourceEntity>>

    @Query(
        value = """
            SELECT *  FROM alarm_resources
            WHERE id = :id
        """
    )fun getAlarmResource(id: Int): Flow<AlarmResourceEntity>

    @Insert(onConflict = OnConflictStrategy.IGNORE)suspend fun insertOrIgnoreAlarmResource(entity: AlarmResourceEntity): Long
}

我正在使用以下 BooleanConverter 将布尔值转换为字符串,反之亦然:

class BooleanConverter {

    @TypeConverterfun charToBoolean(value: Char): Boolean {
        return when(value?: 'F') {
            'T' -> true't' -> trueelse -> false
        }
    }

    @TypeConverterfun booleanToChar(boolean: Boolean): Char {
        return when(boolean) {
            true -> 'T'false -> 'F'
        }
    }
}

现在我想测试数据库操作,但以下测试用例总是失败:

class AlarmResourceDaoTest {
    private val TAG: String = "Morning Walk Alarm"private lateinit var alarmResourceDao: AlarmResourceDao
    private lateinit var db: ScDatabase

    @Beforefun createDb() {
        val context = ApplicationProvider.getApplicationContext<Context>()
        db = Room.inMemoryDatabaseBuilder(
            context,
            ScDatabase::class.java,
        ).build()
        alarmResourceDao = db.alarmResourceDao()
    }

    @Testfun alarmResourceDao_fetches_scheduled_alarms_by_ascending_id() = runTest {
        val alarmResourceEntities = listOf(
            testAlarmResource(
                id = 0,
                label = "Morning Walk",
                scheduledTime = LocalTime.of(5, 0, 0),
                isScheduled = true,
            ),
            testAlarmResource(
                id = 1,
                label = "Lunch",
                scheduledTime = LocalTime.of(12, 0, 0),
                isScheduled = false,
            ),
            testAlarmResource(
                id = 2,
                label = "Dinner",
                scheduledTime = LocalTime.of(8, 0, 0),
                isScheduled = true,
            ),
            testAlarmResource(
                id = 3,
                label = "Android Development",
                scheduledTime = LocalTime.of(9, 0, 0),
                isScheduled = false,
            )
        )
        for( alarmResourceEntity in alarmResourceEntities) {
            alarmResourceDao.insertOrIgnoreAlarmResource(
                alarmResourceEntity
            )
        }

        val morningWalkAlarm = alarmResourceDao.getAlarmResource(0).first()
        Log.i(TAG, "Morning Walk Alarm 1: ${morningWalkAlarm.toString()}")

        val scheduledAlarmResourceEntities = alarmResourceDao.getAllScheduledAlarmResources()
            .first()

        Log.i(TAG, "Morning Walk Alarm 2: ${scheduledAlarmResourceEntities[0].toString()}")

        assertEquals(
            "Morning Walk",
            scheduledAlarmResourceEntities[0].label
        )
    }
}

在测试中,我用 Morning Walk报警 标签记录了两次,但只记录了一次,这是在获取所有计划报警实体之前。

这些是测试运行时的日志:

---------------------------- PROCESS STARTED (17813) for package com.example.clock.core.database ----------------------------
2023-10-24 11:46:19.173 17813-17837 Morning Walk Alarm      com.example.clock.core.database  I  Morning Walk Alarm 1: AlarmResourceEntity(id=0, label=Morning Walk, scheduledTime=05:00, isScheduled=true)
---------------------------- PROCESS ENDED (17813) for package com.example.clock.core.database ----------------------------

这是测试结果:

java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
at jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266)
at java.util.Objects.checkIndex(Objects.java:359)
at java.util.ArrayList.get(ArrayList.java:434)
at com.example.clock.core.database.AlarmResourceDaoTest$alarmResourceDao_fetches_scheduled_alarms_by_ascending_id$1.invokeSuspend(AlarmResourceDaoTest.kt:75)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.test.TestDispatcher.processEvent$kotlinx_coroutines_test(TestDispatcher.kt:28)
at kotlinx.coroutines.test.TestCoroutineScheduler.tryRunNextTaskUnless$kotlinx_coroutines_test(TestCoroutineScheduler.kt:103)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$2$1$workRunner$1.invokeSuspend(TestBuilders.kt:320)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:280)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source:1)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source:1)
at kotlinx.coroutines.test.TestBuildersJvmKt.createTestResult(TestBuildersJvm.kt:13)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:308)
at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0(Unknown Source:1)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:166)
at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0(Unknown Source:1)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0$default(TestBuilders.kt:158)
at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0$default(Unknown Source:1)
at com.example.clock.core.database.AlarmResourceDaoTest.alarmResourceDao_fetches_scheduled_alarms_by_ascending_id(AlarmResourceDaoTest.kt:36)

从测试中,我可以得出结论,插入查询 通过 idAllarmResourceEntity 工作正常,但是当从数据库中获取多个 AlarmResourceEntities 时,问题就出现了。

你能帮我解决这个问题吗?

1 楼 已删除
需要 登录 后方可回复