【问题标题】:Inserting data to the room database from the adapter class crashes the app从适配器类向房间数据库插入数据会使应用程序崩溃
【发布时间】:2022-01-06 18:15:43
【问题描述】:

所以当 onclicklistener 事件发生时,我一直在尝试将数据从适配器类插入房间数据库。但是每次我这样做时,我的应用程序都会崩溃,而 logcat 中没有任何错误消息。事件中唯一发生的事情是数据库实例被创建,一旦发生,应用程序就会崩溃。

我的物品类别:


@Entity(tableName="item")
data class Item(
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0,
    @ColumnInfo(name = "path")
    val path: String,
    @ColumnInfo(name = "name")
    val itemName: String,
)

我的 DAO:

@Dao
interface ItemDao {
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    //suspend is not needed in newer versions of kotlin
    fun insert(item: Item)

}

我的 ItemRoomDatabase.kt :

@Database(entities = [Item::class], version = 1, exportSchema = false)
abstract class ItemRoomDatabase : RoomDatabase() {
    abstract fun itemDao(): ItemDao
    companion object {
        @Volatile
        private var INSTANCE: ItemRoomDatabase? = null
        fun getDatabase(context: Context): ItemRoomDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    ItemRoomDatabase::class.java,
                    "item_database"
                )
                    .fallbackToDestructiveMigration()
                    .build()
                INSTANCE = instance
                return instance
            }
        }
    }
}

我已加星标的应用代码:

class StarredApplication : Application() {
    val database: ItemRoomDatabase by lazy { ItemRoomDatabase.getDatabase(this) }

}

这是我的 InventoryViewModel.kt:

class InventoryViewModel(private val itemDao: ItemDao) : ViewModel()  {

    private fun insertItem(item: Item) {
        viewModelScope.launch {
            itemDao.insert(item)
        }
    }


    fun isEntryValid(path: String, name: String): Boolean {
        if (path.isBlank() || name.isBlank()) {
            return false
        }
        return true
    }

    private fun getNewItemEntry(path: String, name: String): Item {
        return Item(
            path = path,
            itemName = name,
        )
    }

    fun addNewItem(path: String, name: String) {
        val newItem = getNewItemEntry(path, name)
        insertItem(newItem)
    }
}

class InventoryViewModelFactory(private val itemDao: ItemDao) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(InventoryViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return InventoryViewModel(itemDao) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

因此,在我的片段 (PdfContainerFragment.kt) 中,我创建了库存视图模型的 viewModel 实例并将其传递给适配器类。

    private val viewModel: InventoryViewModel by activityViewModels {
        InventoryViewModelFactory(
            (activity?.application as StarredApplication).database.itemDao()
        )
    }

因此,在我的适配器类中,我尝试将数据插入房间数据库,但一旦我单击该事件,应用程序就会崩溃。

// onBindViewHolder里面

     holder.star.setOnClickListener{

            with(model){
                setPath(paths)
            }

            var pdfName = holder.textView.text.toString()
            Log.d("PathPdfContainerAdapter", paths)
            Log.d("pdfNamePdfAdapter", pdfName)

            addNewItem( paths, pdfName)
            holder.star.setImageResource(R.drawable.ic_star_fill)
        }

// Outside onViewBinding

    private fun isEntryValid(path: String, pdfName: String): Boolean {
        return roomViewModel.isEntryValid(
            path,
            pdfName,
        )
    }

    private fun addNewItem( path: String, name: String) {
        if(isEntryValid(path, name)) {
            roomViewModel.addNewItem(
                path,
                name,
            )
        }
    }

我是应用程序开发的新手,所以请把它简单化以便我理解。

【问题讨论】:

  • 使用 Logcat 检查与您的崩溃相关的堆栈跟踪。
  • 嗨。我们无法仅使用应用程序的代码为您提供帮助。使用 logcat 捕获错误并将其粘贴到问题中。这将有很大帮助。 developer.android.com/studio/debug/am-logcat
  • 所以在正常执行我的应用程序时,它会在没有任何日志的情况下崩溃,但我今天刚刚学会了一些使用调试器并发现此错误Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

标签: java android kotlin


【解决方案1】:

所以发生的事情是我的应用程序崩溃,logcat 上没有任何消息,所以我尝试使用调试器并发现异常

Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

因此,在构建数据库时,我将 databaseBuilder 应用到了 allowMainThreadQueries。这不是一个完美的解决方案,但它现在有效。


@Database(entities = [Item::class], version = 1, exportSchema = false)
abstract class ItemRoomDatabase : RoomDatabase() {
    abstract fun itemDao(): ItemDao
    companion object {
        @Volatile
        private var INSTANCE: ItemRoomDatabase? = null
        fun getDatabase(context: Context): ItemRoomDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    ItemRoomDatabase::class.java,
                    "item_database"
                )
                    .fallbackToDestructiveMigration()
                    .allowMainThreadQueries()
                    .build()
                INSTANCE = instance
                return instance
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-01
    • 2020-03-11
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多