获取随机android.database.sqlite.SQLiteBlobTooBigException [英] Getting Random android.database.sqlite.SQLiteBlobTooBigException

查看:194
本文介绍了获取随机android.database.sqlite.SQLiteBlobTooBigException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将应用程序中的Room用作单一真相来源,因此所有来自后端的内容都保存在room数据库中,然后该数据库返回一个Flowable,该Flowable在每次数据更改时触发一个事件.这是我的PlaceSAO:

I am using Room in my app as a Single Source of Truth, so everything that comes from the backend I save in my room database, which then returns a Flowable that fires an event every time the data changes. This is my PlacesDAO:

    @Dao
abstract class PlacesDao {


    @Query("select * from places where placeId = :id")
    abstract fun getPlace(id: String): Flowable<PlaceVO>

    @Query("select * from places where placeId in (:placesIds) order by distance, placeName ASC")
    abstract fun getPlaces(placesIds: List<String>): Flowable<List<PlaceVO>>


    @Query("select * from places join list_results where Places.placeId = list_results.id order by distance, placeName ASC")
    abstract fun getFilteredPlaces(): Flowable<List<PlaceVO>>



    @Query("select * from places join user_places where Places.placeId = user_places.placeId AND user_places.userId = :userId order by distance, placeName ASC ")
    abstract fun getAllByUser(userId: String) : Flowable<List<PlaceVO>>



    @Insert(onConflict = OnConflictStrategy.REPLACE)
    abstract fun realSavePlaces(places:List<PlaceVO>)



    fun savePlaces(places: List<PlaceVO>){
        Timber.w("PAGELIST - Saving places again!!")
        realSavePlaces(places)
    }

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    abstract fun savePlace(place: PlaceVO)



    @Query("DELETE from places")
    abstract fun deleteAll()

    @Query("select * from places")
    abstract fun getAll(): Single<List<PlaceVO>>




    @Query("select * from places where (experienceId IS NOT NULL) AND (experienceId != '') order by placeName")
    abstract fun getMyPlaces(): Flowable<List<PlaceVO>>

    @Query("update places set distance = :distance and distanceSet = 1 where placeId = :id")
    abstract fun updateDistance(id: String, distance: Float)
}

现在,在我的应用程序中,有一些操作将触发更改此表中的数据,然后使我的UI接收表中包含的所有项(大约3000-5000).

Now in my app theres a few actions that would trigger changing the data in this table, which then causes my UI to receive all items contained in the table (around 3000-5000).

它确实总是在发生(这很难复制),但是我时不时地会遇到以下崩溃:

It does niot always happen (which makes it hard to reproduce) but every now and then I will get the following crash:

Caused by android.database.sqlite.SQLiteBlobTooBigException: Row too big to fit into CursorWindow requiredPos=1223, totalRows=114
       at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(SQLiteConnection.java)
       at android.database.sqlite.SQLiteConnection.executeForCursorWindow + 895(SQLiteConnection.java:895)
       at android.database.sqlite.SQLiteSession.executeForCursorWindow + 836(SQLiteSession.java:836)
       at android.database.sqlite.SQLiteQuery.fillWindow + 62(SQLiteQuery.java:62)
       at android.database.sqlite.SQLiteCursor.fillWindow + 157(SQLiteCursor.java:157)
       at android.database.sqlite.SQLiteCursor.onMove + 128(SQLiteCursor.java:128)
       at android.database.AbstractCursor.moveToPosition + 237(AbstractCursor.java:237)
       at android.database.AbstractCursor.moveToNext + 269(AbstractCursor.java:269)
       at com.myapp.android.model.db.dao.PlacesDao_Impl$6.call + 814(PlacesDao_Impl.java:814)
       at com.myapp.android.model.db.dao.PlacesDao_Impl$6.call + 771(PlacesDao_Impl.java:771)
       at io.reactivex.internal.operators.maybe.MaybeFromCallable.subscribeActual + 46(MaybeFromCallable.java:46)
       at io.reactivex.Maybe.subscribe + 4262(Maybe.java:4262)
       at io.reactivex.internal.operators.flowable.FlowableFlatMapMaybe$FlatMapMaybeSubscriber.onNext + 132(FlowableFlatMapMaybe.java:132)
       at io.reactivex.internal.operators.flowable.FlowableObserveOn$ObserveOnSubscriber.runAsync + 407(FlowableObserveOn.java:407)
       at io.reactivex.internal.operators.flowable.FlowableObserveOn$BaseObserveOnSubscriber.run + 176(FlowableObserveOn.java:176)
       at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker$BooleanRunnable.run + 260(ExecutorScheduler.java:260)
       at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.run + 225(ExecutorScheduler.java:225)
       at java.util.concurrent.ThreadPoolExecutor.runWorker + 1167(ThreadPoolExecutor.java:1167)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run + 641(ThreadPoolExecutor.java:641)
       at java.lang.Thread.run + 764(Thread.java:764)

正如该课程所证明的,我仅存储文本信息:

I am only storing text info, as proved by this class:

@Entity(tableName = "places")
data class PlaceVO(
        @PrimaryKey
        var placeId: String,

        var googleId: String,

        var placeName: String,

        var phoneNumber: String,

        @Embedded
        var primaryCategory: Category?,

        var primaryCategoryTags: List<CategoryTag> = emptyList(),

        var secondaryCategories: List<Category>? = emptyList(),

        var images: List<Image>,

        var website: String,

        var formattedAddress: String? = "",

        var vicinity: String = "",

        var vicinityShort: String = "",

        var city: String? = "",

        var neighbourhood: String?,

        var longitude: Double,

        var latitude: Double,

        var openingHours: List<String>,

        var combinedHighlights: List<HighlightCountWrapper>,
        @Embedded
        var ownExperience: OwnExperience?,

        var otherExperiences: List<Experience>,

        var distance: Float?,

        var distanceSet: Boolean = false,

        var comment: String
) : MarkerPlace {

}

体验班:

@Entity
data class Experience(
        @Json(name="id")
        val experienceId: String,
        @Embedded
        val owner: User,
        val description: String?,
        val highlights: List<Highlight>?,
        val images: List<Image> = emptyList(),
        val createdDate: Date,
        val updatedDate: Date,
        var privacyLevel: AddExperience.Privacy? = null)

某些TypeConverters:

Some TypeConverters:

@TypeConverter
    fun toHighlightWrapperList(value: String): List<HighlightCountWrapper> {
        val type = Types.newParameterizedType(List::class.java, HighlightCountWrapper::class.java)
        return moshi.adapter<List<HighlightCountWrapper>>(type).fromJson(value) ?: emptyList()
    }

    @TypeConverter
    fun fromHighlightWrapperList(list: List<HighlightCountWrapper>): String {
        val type = Types.newParameterizedType(List::class.java, HighlightCountWrapper::class.java)
        var adapter: JsonAdapter<List<HighlightCountWrapper>> = moshi.adapter<List<HighlightCountWrapper>>(type)
        return adapter.toJson(list)
    }

 @TypeConverter
    fun toExperienceList(value: String): List<Experience> {
        val type = Types.newParameterizedType(List::class.java, Experience::class.java)
        return moshi.adapter<List<Experience>>(type).fromJson(value) ?: emptyList()
    }

    @TypeConverter
    fun fromExperienceList(list: List<Experience>): String {
        val type = Types.newParameterizedType(List::class.java, Experience::class.java)
        var adapter: JsonAdapter<List<Experience>> = moshi.adapter<List<Experience>>(type)
        return adapter.toJson(list)
    }

@TypeConverter
    fun toImageList(value: String): List<Image> {
        val type = Types.newParameterizedType(List::class.java, Image::class.java)
        return moshi.adapter<List<Image>>(type).fromJson(value) ?: emptyList()
    }

    @TypeConverter
    fun fromImageList(list: List<Image>): String {
        val type = Types.newParameterizedType(List::class.java, Image::class.java)
        var adapter: JsonAdapter<List<Image>> = moshi.adapter<List<Image>>(type)
        return adapter.toJson(list)
    }

那么对于SQLite我的行太大了怎么办?尤其是有时候有时会返回完全相同的数据而没有问题吗?

so how can it be that my rows are too big for SQLite? Especially when sometimes exactly the same data will be returned without a problem?

推荐答案

我发现了如何使用length()和substr()仅请求1MB(CursorWindow的最大值为2MB),也许它会

I found how to use length() and substr() to request only 1MB (the max for CursorWindow is 2MB), maybe it will help. (in your case you could simply divide the requests into chunks of 100 rows and then close the cursor, then repeat) It seems that you are storing images, in which case it would be better to store them in internal storage, and only store the file path in the database.

尤其是有时有时会返回完全相同的数据而不会出现问题吗?

Especially when sometimes exactly the same data will be returned without a problem?

如果您指的是完全相同的行(例如从1000到2000的行),但是来自不同的设备,则可能是CursorWindow具有不同的最大尺寸",在我看来,这是2MB.

If you mean exactly the same rows (like the rows from 1000 to 2000), but from different devices, it might be the case that they have different "max-sizes" for the CursorWindow, in my case it seems to be 2MB.

这篇关于获取随机android.database.sqlite.SQLiteBlobTooBigException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆