Android Kotlin项目中Realm读写无数据问题排查求助
Realm写入后无法读取数据的问题排查与修复
核心问题分析
- Realm实例线程绑定:主线程初始化的
realm实例不能跨线程调用executeTransaction,Realm对象是线程独占的,跨线程使用会直接导致数据写入失败。 - 未处理输入异常:
editTextInt.text.toString().toInt()如果输入非数字会抛出NumberFormatException,直接中断写入流程且无错误提示。 - 事务执行不规范:子线程中未正确获取和关闭Realm实例,可能引发资源泄漏或数据写入异常。
修复后的代码实现
1. 数据类(保持原有结构)
open class DataItemExtra : RealmObject { @PrimaryKey var id: String? = null var strVal: String = "" var intVal: Int = 0 var extra: String = "extra" constructor(id: String?, s: String, n: Int) { this.id = id this.strVal = s this.intVal = n } constructor() // Realm要求的空构造函数 }
2. Activity代码修复
class MainActivity : AppCompatActivity() { private lateinit var realmConfig: RealmConfiguration override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val buttonSet = findViewById<Button>(R.id.buttonSet) val buttonGet = findViewById<Button>(R.id.buttonGet) val editTextString = findViewById<EditText>(R.id.editText) val editTextInt = findViewById<EditText>(R.id.editNum) val textRes = findViewById<TextView>(R.id.textRes) Realm.init(this) val realmName = "My Project" realmConfig = RealmConfiguration.Builder() .schemaVersion(1) .deleteRealmIfMigrationNeeded() .name(realmName) .build() buttonSet.setOnClickListener { val strVal = editTextString.text.toString().trim() val intStr = editTextInt.text.toString().trim() // 输入校验 if (strVal.isEmpty() || intStr.isEmpty()) { Toast.makeText(this, "请输入完整内容", Toast.LENGTH_SHORT).show() return@setOnClickListener } val intVal = try { intStr.toInt() } catch (e: NumberFormatException) { Toast.makeText(this, "请输入有效数字", Toast.LENGTH_SHORT).show() return@setOnClickListener } Toast.makeText(this, "$strVal : $intVal", Toast.LENGTH_LONG).show() // 子线程独立获取Realm实例执行写入 Thread { Realm.getInstance(realmConfig).use { realm -> realm.executeTransaction { transactionRealm -> val di = DataItemExtra("keyVal", strVal, intVal) transactionRealm.insertOrUpdate(di) } } // 主线程提示写入结果 runOnUiThread { Toast.makeText(this, "数据写入成功", Toast.LENGTH_SHORT).show() } }.start() } buttonGet.setOnClickListener { // 主线程获取Realm实例读取数据 Realm.getInstance(realmConfig).use { realm -> val tasks: RealmResults<DataItemExtra> = realm.where<DataItemExtra>().findAll() textRes.text = "" val rSize = tasks.size if (rSize != 1) { textRes.text = "数据数量异常:$rSize" } else { val d = tasks[0] textRes.text = "${d.id}, ${d.strVal}, ${d.intVal}, ${d.extra}" } tasks.forEach { d -> Log.d("REALM-RES", "${d.id}, ${d.strVal}, ${d.intVal}, ${d.extra}") } } } } }
关键修改说明
线程安全的Realm实例管理:
- 不再全局持有Realm实例,而是在需要的线程中通过
Realm.getInstance(realmConfig)获取,并用use函数自动关闭,避免资源泄漏。 - 写入操作在子线程独立获取实例,严格遵循Realm线程绑定规则。
- 不再全局持有Realm实例,而是在需要的线程中通过
输入校验与异常捕获:
- 增加空值和数字格式校验,避免因输入错误导致写入流程中断。
数据读取规范:
- 读取时在主线程正确获取Realm实例,确保能拿到实时更新的数据。
额外建议
- 推荐使用Realm Kotlin扩展库(
io.realm:realm-ktx),可以用realm.write { ... }简化事务操作,代码更简洁。 - 读取大量数据时建议放在子线程执行,避免阻塞UI线程。
内容的提问来源于stack exchange,提问作者Yura
相关产品推荐
相关产品推荐

