【发布时间】:2022-01-24 19:56:52
【问题描述】:
我正在为 Android 创建一个像素艺术编辑器应用程序,我有两个数据库,一个存储用户的创作,另一个存储用户的调色板。
这是调色板数据库的代码:
package com.realtomjoney.pyxlmoose.database
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
import com.realtomjoney.pyxlmoose.converters.JsonConverter
import com.realtomjoney.pyxlmoose.dao.ColorPalettesDao
import com.realtomjoney.pyxlmoose.models.ColorPalette
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.concurrent.Executors
@Database(entities = [ColorPalette::class], version = 3)
abstract class ColorPalettesDatabase: RoomDatabase() {
abstract fun colorPalettesDao(): ColorPalettesDao
companion object {
private var instance: ColorPalettesDatabase? = null
fun getDatabase(context: Context): ColorPalettesDatabase {
if (instance == null) {
synchronized(ColorPalettesDatabase::class) {
if (instance == null) instance = Room.databaseBuilder(context.applicationContext, ColorPalettesDatabase::class.java, AppData.colorPalettesDBFileName).fallbackToDestructiveMigration().addCallback(object : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
Executors.newSingleThreadExecutor().execute {
CoroutineScope(Dispatchers.IO).launch {
instance?.colorPalettesDao()?.insertColorPalette(ColorPalette("Default color palette", JsonConverter.convertListOfIntToJsonString(ColorDatabase.toList()), true))
}
}
}
}).allowMainThreadQueries().build()
}
}
return instance!!
}
}
}
首次创建 Room 数据库时,会添加“默认”调色板。
道:
@Dao
interface ColorPalettesDao {
@Insert
suspend fun insertColorPalette(colorPalette: ColorPalette)
@Query("SELECT * FROM ColorPalette")
fun getAllColorPalettes(): LiveData<List<ColorPalette>>
@Query("DELETE FROM ColorPalette WHERE objId=:colorPaletteId")
fun deleteColorPalette(colorPaletteId: Int)
@Query("UPDATE ColorPalette SET item_color_palette_color_data=:colorData WHERE objId=:id_t")
fun updateColorPaletteColorData(colorData: String, id_t: Int)
}
应用数据:
class AppData {
companion object {
var pixelArtDBFileName = "pixel_art_db"
lateinit var pixelArtDB: PixelArtDatabase
var colorPalettesDBFileName = "color_palettes_db"
lateinit var colorPalettesDB: ColorPalettesDatabase
}
}
数据像这样加载到 RecyclerView 中:
fun CanvasActivity.extendedSetUpRecyclerView() {
val layoutManager = GridLayoutManager(this, 1)
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
binding.activityCanvasColorPickerRecyclerView.layoutManager = layoutManager
AppData.colorPalettesDB.colorPalettesDao().getAllColorPalettes().observe(this) {
val toShow = if (fromDB != null) fromDB else it.first()
binding.activityCanvasColorPickerRecyclerView.adapter = ColorPickerAdapter(toShow!!, this)
}
}
以下是我的一些 Espresso 测试:
@LargeTest
@RunWith(AndroidJUnit4ClassRunner::class)
class CanvasActivityTest {
@get:Rule
var activityTestRule = ActivityScenarioRule(CanvasActivity::class.java)
@Test fun uitest_activityCanvasRootLayout_childViews_doNotExist() {
for (id in EspressoUtilities.getActivityCanvasRootLayoutChildElementIds()) onView(withId(id)).check(matches(isDisplayed()))
}
@Test fun uitest_fullscreenMenuItem_isDisplayed() {
onView(withId(R.id.fullscreen)).check(matches(isDisplayed()))
}
@Test fun uitest_undoMenuItem_isDisplayed() {
onView(withId(R.id.undo)).check(matches(isDisplayed()))
}
@Test fun uitest_zoomIn_isDisplayed() {
onView(withId(R.id.zoom_in)).check(matches(isDisplayed()))
}
@Test fun uitest_zoomOut_isDisplayed() {
onView(withId(R.id.zoom_out)).check(matches(isDisplayed()))
}
@Test fun uitest_saveProject_isDisplayed() {
onView(withId(R.id.save_project)).check(matches(isDisplayed()))
}
}
运行 Espresso 测试会导致以下异常:
kotlin.UninitializedPropertyAccessException: lateinit property colorPalettesDB has not been initialized
at com.realtomjoney.pyxlmoose.database.AppData$Companion.getColorPalettesDB(AppData.kt:9)
at com.realtomjoney.pyxlmoose.activities.canvas.CanvasActivity_setUpRecyclerViewKt.extendedSetUpRecyclerView(CanvasActivity+setUpRecyclerView.kt:15)
at com.realtomjoney.pyxlmoose.activities.canvas.CanvasActivity.setUpRecyclerView(CanvasActivity.kt:45)
at com.realtomjoney.pyxlmoose.activities.canvas.CanvasActivity_onCreateKt.extendedOnCreate(CanvasActivity+onCreate.kt:13)
at com.realtomjoney.pyxlmoose.activities.canvas.CanvasActivity.onCreate(CanvasActivity.kt:19)
at android.app.Activity.performCreate(Activity.java:8051)
at android.app.Activity.performCreate(Activity.java:8031)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
at androidx.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:769)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3612)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3796)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2214)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7842)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
这很奇怪,因为colorPalettesDB 在这个阶段应该已经被初始化了。存储用户创作的另一个数据库没有引起任何问题,但由于某种原因,ColorPalettesDatabase 是导致这些异常的数据库。在 onCreate 和 Espresso 代码中第二次初始化它并不能解决问题,所以我很困惑如何解决这个问题,因为我不确定错误的根源是什么。
添加
Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(),ColorPalettesDatabase::class.java).build()
...不能解决问题。
这里是初始化数据库的地方:
fun MainActivity.initializeRoomDatabases() {
AppData.pixelArtDB = PixelArtDatabase.getDatabase(this)
AppData.colorPalettesDB = ColorPalettesDatabase.getDatabase(this)
}
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setBindings()
setOnClickListeners()
setTitle()
initializeRoomDatabases()
}
【问题讨论】:
-
那么您的代码在哪里初始化该变量?为什么您的代码根本不调用
ColorPalettesDatabase.getInstance(context)而不是使用lateinit变量? -
@ianhanniballake 因为 AppData 只是一个
Object它无法访问应用程序上下文...这就是为什么需要从 Activity 调用它的原因。如果我做的不对,请告诉我,代码的大部分结构都是基于 Udemy 课程。 -
也许你在 setBindings() 中使用 colorPalettesDB,因为在你的堆栈跟踪中有一个地方说在这部分代码尝试使用 colorPalettesDB:CanvasActivity_setUpRecyclerViewKt.extendedSetUpRecyclerView
-
@MohammadRezaKhahani 对不起,我不关注。
标签: android kotlin android-room android-espresso