I learning Room library for creating apps with sqlite database, but I get an error. In the first launching when I add item to DB, it navigate to fragment with RecyclerView and after 1 second my app crashes.
Error
E/SQLiteQuery: exception: Row too big to fit into CursorWindow requiredPos=0, totalRows=1; query: SELECT * FROM vet_product ORDER BY id ASC
E/AndroidRuntime: FATAL EXCEPTION: arch_disk_io_0
Process: com.dimon.vetdatabasemobile, PID: 26700
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:923)
Caused by: android.database.sqlite.SQLiteBlobTooBigException: Row too big to fit into CursorWindow requiredPos=0, totalRows=1
at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method)
at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:1001)
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:838)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:153)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:140)
at com.dimon.vetdatabasemobile.db.dao_s.ProductDao_Impl$5.call(ProductDao_Impl.java:172)
at com.dimon.vetdatabasemobile.db.dao_s.ProductDao_Impl$5.call(ProductDao_Impl.java:163)
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:923)
My models
@Parcelize
@Entity(tableName = "vet_product")
data class Product(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
val productName: String,
val productPrice: Double,
val productImage: Bitmap
) : Parcelable
@Parcelize
@Entity(tableName = "cart")
data class CartModel(
@PrimaryKey(autoGenerate = true) val id: Long = 0,
val productName: String,
val productPrice: Double
) : Parcelable
My DAOs
@Dao
interface ProductDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(product: Product)
@Delete
fun delete(product: Product)
@Update
fun update(product: Product)
@Query("DELETE FROM vet_product")
fun deleteAll()
@Query("SELECT * FROM vet_product ORDER BY id ASC")
fun getAllProducts(): LiveData<List<Product>>
}
@Dao
interface CartDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insertToCart(cartModel: CartModel)
@Query("DELETE FROM cart")
fun deleteAllFromCart()
@Query("SELECT * FROM cart ORDER BY id ASC")
fun getCartModels(): LiveData<List<CartModel>>
}
My repositories
class ProductRepository(private val productDao: ProductDao) {
val getAllProduct: LiveData<List<Product>> = productDao.getAllProducts()
fun addProduct(product: Product) {
productDao.insert(product)
}
fun updateProduct(product: Product) {
productDao.update(product)
}
fun deleteProduct(product: Product) {
productDao.delete(product)
}
fun deleteAllProducts() {
productDao.deleteAll()
}
}
class CartRepository(private val cartDao: CartDao) {
val getAllCartModels: LiveData<List<CartModel>> = cartDao.getCartModels()
fun addToCart(cartModel: CartModel) {
cartDao.insertToCart(cartModel)
}
fun deleteAllFromCart() {
cartDao.deleteAllFromCart()
}
}
My viewmodels
class ProductViewModel(application: Application) : AndroidViewModel(application) {
val getAllProducts: LiveData<List<Product>>
private val repository: ProductRepository
init {
val productDao = VetDatabase.getInstance(application).productDao()
repository = ProductRepository(productDao)
getAllProducts = repository.getAllProduct
}
fun addProduct(product: Product) {
viewModelScope.launch(Dispatchers.IO) {
repository.addProduct(product)
}
}
fun updateProduct(product: Product) {
viewModelScope.launch(Dispatchers.IO) {
repository.updateProduct(product)
}
}
fun deleteProduct(product: Product) {
viewModelScope.launch(Dispatchers.IO) {
repository.deleteProduct(product)
}
}
fun deleteAllProducts() {
viewModelScope.launch(Dispatchers.IO) {
repository.deleteAllProducts()
}
}
}
class CartViewModel(application: Application) : AndroidViewModel(application) {
val getCartModels: LiveData<List<CartModel>>
private val repository: CartRepository
init {
val cartDao = VetDatabase.getInstance(application).cartDao()
repository = CartRepository(cartDao)
getCartModels = repository.getAllCartModels
}
fun addToCart(cartModel: CartModel) {
viewModelScope.launch(Dispatchers.IO) {
repository.addToCart(cartModel)
}
}
fun deleteAllFromCart() {
viewModelScope.launch(Dispatchers.IO) {
repository.deleteAllFromCart()
}
}
}
My DB
@Database(entities = [Product::class, CartModel::class], version = 5, exportSchema = false)
@TypeConverters(Converters::class)
abstract class VetDatabase : RoomDatabase() {
abstract fun productDao(): ProductDao
abstract fun cartDao(): CartDao
companion object {
@Volatile
private var INSTANCE: VetDatabase? = null
fun getInstance(context: Context): VetDatabase {
val tempInstance = INSTANCE
if (tempInstance != null) {
return tempInstance
}
synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
VetDatabase::class.java,
"vet_db"
)
.fallbackToDestructiveMigration()
.allowMainThreadQueries()
.build()
INSTANCE = instance
return instance
}
}
}
}
But I noticed that problem with images. With some images item adds to DB succesfully but with other images it adds with crashing. I don't know how to fix this, in the Internet I found nothing. Maybe someone knows how to fix this error?
In advance thanks fow helping!
CodePudding user response:
You issue is that as described as per Row too big to fit into CursorWindow requiredPos=0, totalRows=1
Although you have successfully stored the data, it is too large for extraction. A CursorWindow MUST be able to store at least 1 full row.
- CursorWindows have a storage limit between 1Mb and 4Mb (dependant upon the device and it's API/version).
Images, such as bitmaps, are frequently larger than the limit. It is inadvisable to store images in a database.
The recommendation is to store the image as a file and to then store the path or enough of the path to discern the image from others in the database.
- There are ways that the data can be accessed, such as in chunks. E.g. you could extract the length of the column and then extract parts and combine them. However, such methods are not recommended as they would very likely be inefficient.