如何在DB Browser for SQLite中存储drawable图片预填充Room数据库
问题原因
你遇到的报错本质原因很简单:R.drawable.mike是Android项目编译阶段由AAPT自动生成的int类型常量,仅在Android代码运行环境下存在。DB Browser for SQLite是独立的外部工具,没有Android的R类上下文,会把你写的R.drawable.mike识别成字段名,自然报「不存在该列」的错误,这和你把image字段改成BLOB类型没有任何关系。
可行实现方案
方案1:image字段存字符串,运行时动态解析资源ID
不需要存完整的R.drawable.mike字符串,直接存drawable文件的文件名即可(比如对应R.drawable.mike就存"mike"),预填充SQL写法如下:
INSERT INTO player (name,score,image) VALUES ("Mike", 31, "mike")
从数据库读取到字符串后,调用Resources.getIdentifier()方法反射获取对应资源ID即可使用:
// 假设从数据库读取出的图片字段值为imgName: String val drawableResId = context.resources.getIdentifier( imgName, "drawable", context.packageName ) // 判空避免资源不存在的情况 if (drawableResId != 0) { imageView.setImageResource(drawableResId) }
注意点:
- 字符串大小写必须和drawable目录下的文件名完全一致,否则会返回0(资源查找失败)
- 该方法基于反射实现,数据量不大的场景下性能损耗可以忽略
方案2:直接存储资源ID的数值(保留image字段Int类型)
R类对应的资源ID本质是固定数值,你可以先在Android代码里打印出目标drawable的实际ID值:
Log.d("res_check", "mike的drawable ID是:${R.drawable.mike}")
运行一次代码拿到控制台输出的int数值(通常是10位数字,比如2131165327),直接把这个数值写到DB Browser的插入语句里即可:
INSERT INTO player (name,score,image) VALUES ("Mike", 31, 2131165327)
读取时直接取出int值传给setImageResource()即可使用,没有额外性能损耗。
注意点:
- Android资源ID会随着资源增减、编译版本变化重新生成,如果后续版本有drawable资源变动,需要同步更新预填充数据库里的ID值,否则会出现资源找不到的问题
方案3:不用外部工具,在Room创建回调里直接预填充(最稳妥)
这是Room官方推荐的预填充方式,完全绕开外部工具无法识别R类的问题:在数据库首次创建的回调里,直接在Android环境下执行插入语句,此时可以直接引用R类常量,ID永远和当前编译版本匹配,不会出现失效问题:
val db = Room.databaseBuilder( context.applicationContext, AppDatabase::class.java, "player_db" ).addCallback(object : RoomDatabase.Callback() { override fun onCreate(db: SupportSQLiteDatabase) { super.onCreate(db) // 直接在代码里插预填充数据,可正常引用R类 db.execSQL("INSERT INTO player (name,score,image) VALUES ('Mike', 31, ${R.drawable.mike})") // 其余预填充数据按相同写法添加即可 } }).build()
内容的提问来源于stack exchange,提问作者Grim Reaper
相关产品推荐
相关产品推荐

