I am creating a pixel art editor app and I already have one Room database which stores the users' creations and another Room database which I want to add which will store some custom color palettes the user wants to add to the app.
To do this I added the following database:
@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).allowMainThreadQueries().build()
}
}
return instance!!
}
}
}
And the DAO:
@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)
}
I added a variable in AppData
and initialized it in the MainActivity's onCreate
method:
class AppData {
companion object {
var pixelArtDBFileName = "pixel_art_db"
lateinit var pixelArtDB: PixelArtDatabase
var colorPalettesDBFileName = "color_palettes_db"
lateinit var colorPalettesDB: ColorPalettesDatabase
}
}
AppData.colorPalettesDB = ColorPalettesDatabase.getDatabase(this)
And finally, I use get the ColorPalette
data from the database in the ColorPalettesFragment.kt
file:
class ColorPalettesFragment(private val lifecycleOwner: LifecycleOwner) : Fragment(), ColorPalettesListener {
private var _binding: FragmentColorPalettesBinding? = null
private val binding get() = _binding!!
private lateinit var caller: ColorPalettesFragmentListener
private fun setUpRecyclerView() {
binding.apply {
fragmentColorPalettesRecyclerView.layoutManager = LinearLayoutManager(this@ColorPalettesFragment.activity).apply {
orientation = LinearLayoutManager.HORIZONTAL
}
AppData.colorPalettesDB.colorPalettesDao().getAllColorPalettes().observe(lifecycleOwner) {
fragmentColorPalettesRecyclerView.adapter = ColorPalettesAdapter(it, this@ColorPalettesFragment)
}
}
}
companion object {
fun newInstance(lifecycleOwner: LifecycleOwner) = ColorPalettesFragment(lifecycleOwner)
}
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is ColorPalettesFragmentListener) caller = context
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentColorPalettesBinding.inflate(inflater, container, false)
setUpRecyclerView()
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onColorPaletteTapped(selectedColorPalette: ColorPalette) {
caller.onColorPaletteTapped(selectedColorPalette)
}
}
So far I'm testing it when the database is empty, what I expect is whenever the user taps the following button they will see a blank RecyclerView
:
Unfortunately, I can't even get to the screen as when I run the app and try to navigate to the Canvas I get the following exception:
2021-12-22 08:55:57.251 24474-24554/com.realtomjoney.pyxlmoose E/AndroidRuntime: FATAL EXCEPTION: arch_disk_io_1
Process: com.realtomjoney.pyxlmoose, PID: 24474
java.lang.RuntimeException: Exception while computing database live data.
at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:92)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:920)
Caused by: java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.
at androidx.room.RoomOpenHelper.checkIdentity(RoomOpenHelper.java:154)
at androidx.room.RoomOpenHelper.onOpen(RoomOpenHelper.java:135)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onOpen(FrameworkSQLiteOpenHelper.java:201)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:427)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:316)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:151)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:112)
at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:706)
at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:483)
at androidx.room.RoomDatabase.query(RoomDatabase.java:526)
at androidx.room.util.DBUtil.query(DBUtil.java:86)
at com.realtomjoney.pyxlmoose.dao.ColorPalettesDao_Impl$4.call(ColorPalettesDao_Impl.java:108)
at com.realtomjoney.pyxlmoose.dao.ColorPalettesDao_Impl$4.call(ColorPalettesDao_Impl.java:105)
at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:90)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:920)
I've tried to look at other solutions for a fix but nothing seems to help.
This is coming from the ColorPalettesDatabase
as when I remove all of its usages in code the exception goes away.
Updating the version unfortunately doesn't help and so doesn't uninstalling the app.