首页 > 解决方案 > 在使用位图类型转换器类时从 ROOM 数据库中多次查询行会使应用程序崩溃

问题描述

所以我有一个带有分页适配器的 Recycler View,recycler view 列表项有一个 imageView 和几个文本视图。适配器正在从另一个 ROOM 数据库中检索 textViews 的数据,而从另一个 ImageHolder ROOM 数据库中检索每个特定列表项的图像。

在适配器的 onBind 方法中,除了绑定 textViews 之外,还有对关联图像的 ImageHolder ROOM 数据库的单独调用。Recycler View 有大约 100 个项目,当 UI 快速滚动时,对 ImageHolder 数据库进行了大约 100 个查询。这很好用,但是当用户滚动并崩溃应用程序时,它会减慢应用程序的速度。我该如何避免崩溃?

这是代码:

数据类

@Entity(tableName = IMAGE_HOLDER_TABLE)
data class ImageHolder(

    @PrimaryKey(autoGenerate = false)
    var contentId: String = "",
    var imageBitmap : Bitmap,  // I am using a Converter class to convert a Bitmap to a ByteArray
    var timeStamp : Long = System.currentTimeMillis()
)

道接口

@Dao
interface ImageHolderDatabaseDao {

    @Query("SELECT * FROM $IMAGE_HOLDER_TABLE WHERE contentId = :contentId")
    suspend fun getImageHolder(contentId : String): ImageHolder

    @Query("SELECT imageBitmap FROM $IMAGE_HOLDER_TABLE WHERE contentId = 
    :contentId")
    suspend fun getImage(contentId : String): Bitmap
}

Adapter的onBindViewHolder方法中获取图片的方法

val imageHolderDatabase = ImageHolderDatabase.instance(getApplicationContext())
    val imageHolderDatabaseDao = imageHolderDatabase.databaseDao
    private val scope = CoroutineScope(Dispatchers.Main +  
CoroutineName("notificationsAdapterCoroutine"))

    private fun populatePhotoFromLocalDb(senderUserId : String) {
        scope.launch {
            val imageBitmap = imageHolderDatabase.withTransaction {
                imageHolderDatabaseDao.getImageHolder(senderUserId)
            }

            Glide.with(getApplicationContext())
                .load(imageBitmap.imageBitmap)
                .placeholder(R.drawable.black_color_rectangle)
                .apply(glideRequestOptionsForCache)
                .transition(DrawableTransitionOptions.withCrossFade(glideCrossFadeDuration))
                .listener(glideFinishedLoadingListener(senderUserId, true, null))
                .into(binding.image)
        }
    }
//I am using the Paging 3 adapter to populate the textViews from another Room Database

我意识到对 ImageHolder Room 数据库进行了 100 次查询调用,因为 Recycler 视图中有 100 个项目。我正在使用 Glide 但现在不使用它的缓存。

什么是内存有效的方法来做到这一点?

标签: androidandroid-roomkotlin-coroutinesandroid-paging

解决方案


从 ByteArray 到 Bitmap 的类型转换器导致过多的内存使用,这实际上是存储图像的好方法,但使用方便的 ROOM 类型转换器的用例错误(除非它用于非 recyclerView 适配器),我有更改了逻辑以仅将 downloadUrls 存储在 Room Db 中,并使用 glide 通过下载 Url 加载图像,因为 glide 内置了离线缓存系统,即使互联网暂时不可用,此逻辑也适用...


推荐阅读