You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ViewModel读取Room数据库数据到TextView时应用崩溃问题解决

问题解答:Room空数据导致TextView显示崩溃,RecyclerView却正常的原因及修复方案

问题描述

开发了一个结合TextView与Room数据库的简单应用:数据库有数据时,将内容显示在TextView中;首次启动数据库为空时,通过ViewModel读取数据并显示到TextView会导致应用崩溃,但使用RecyclerView仅显示空列表不会崩溃。

相关代码

Fragment代码

class HomeFragment : Fragment() {

private lateinit var viewModel: MyViewModel
override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_home, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    viewModel = ViewModelProvider(this)[MyViewModel::class.java]
    viewModel.getAllDataObservers().observe(viewLifecycleOwner){

        //textview for show data
        txt_show_number.text = it[0].question_number
        txt_show_question.text = it[0].question

    }
}

ViewModel代码

class MyViewModel(application: Application) : AndroidViewModel(application) {

var allUsers: MutableLiveData<List<EntityStudent>> = MutableLiveData()

fun getAllDataObservers(): MutableLiveData<List<EntityStudent>> {
    getAllData()
    return allUsers
}

fun getAllData() {
    val dao = RoomDb.getAppDatabase((getApplication()))?.mainDao()
    val list = dao?.getAllData()
    allUsers.postValue(list!!)
}

fun insert(entityStudent: EntityStudent) {
    val dao = RoomDb.getAppDatabase((getApplication()))?.mainDao()
    val list = dao?.insert(entityStudent)
    getAllData()
}

报错信息

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.student, PID: 2679
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.get(ArrayList.java:437)
    at com.example.student.HomeFragment.onViewCreated$lambda-0(HomeFragment.kt:32)
    at com.example.student.HomeFragment.$r8$lambda$kFVd0uSVK9JwnEU47m0mSdTzXmo(Unknown Source:0)
    at com.example.student.HomeFragment$$ExternalSyntheticLambda0.onChanged(Unknown Source:4)

第32行代码:txt_show_number.text = it[0].question_number

原因分析

  • TextView崩溃原因:数据库为空时,Room返回的List<EntityStudent>是空列表(Size为0),但你直接通过it[0]去取第一个元素,触发了IndexOutOfBoundsException数组越界异常,直接导致应用崩溃。
  • RecyclerView正常原因:RecyclerView的Adapter内部默认会处理空列表的情况——当数据源为空时,Adapter不会执行绑定视图的逻辑,自然不会触发越界异常,只会显示空白列表。

修复方案

1. Fragment中添加空列表判断(最直接修复)

在LiveData的观察者中,先判断列表是否为空,再决定是显示数据还是空提示:

viewModel.getAllDataObservers().observe(viewLifecycleOwner){ studentList ->
    if (studentList.isNotEmpty()) {
        txt_show_number.text = studentList[0].question_number
        txt_show_question.text = studentList[0].question
    } else {
        // 数据库为空时显示提示文本
        txt_show_number.text = "暂无数据"
        txt_show_question.text = "请添加数据"
    }
}

2. 优化ViewModel中的代码(避免潜在空指针)

ViewModel中使用了非空断言!!,如果Room数据库初始化失败或者Dao获取失败,list!!会直接抛出空指针异常,建议改为安全处理:

fun getAllData() {
    val dao = RoomDb.getAppDatabase(getApplication())?.mainDao()
    val list = dao?.getAllData() ?: emptyList() // 为空时返回空列表,而非null
    allUsers.postValue(list)
}

3. 可选:默认插入初始化数据(按需使用)

如果应用首次启动必须要有数据显示,可以在数据库创建时插入默认数据,比如在RoomDatabase的callback中实现:

@Database(entities = [EntityStudent::class], version = 1)
abstract class RoomDb : RoomDatabase() {
    abstract fun mainDao(): MainDao

    companion object {
        fun getAppDatabase(context: Context): RoomDb? {
            return Room.databaseBuilder(context, RoomDb::class.java, "student_db")
                .addCallback(object : Callback() {
                    override fun onCreate(db: SupportSQLiteDatabase) {
                        super.onCreate(db)
                        // 插入默认数据
                        CoroutineScope(Dispatchers.IO).launch {
                            getAppDatabase(context)?.mainDao()?.insert(EntityStudent(question_number = "1", question = "默认问题"))
                        }
                    }
                })
                .build()
        }
    }
}

内容的提问来源于stack exchange,提问作者Hosein.m.barazandeh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 11:06:19