如何在房间持久性库中插入图像?
How insert image in room persistence library?
我正在为我的 android 应用程序使用房间持久性库,现在我必须在我的数据库中插入图像。我成功地为原始数据类型定义了@Entity。还通过转换器 class,我存储了所有对象、日期和时间。现在我必须存储图像。我无法理解我们如何定义列信息和实体以及我们如何插入该数据以及从 table.
中读取数据
插入单行的最大数据量是多少? Android SQLite 中一个字段中数据的最大和最小大小是多少?
通常不建议将图像数据存储到数据库中。
但是,如果您的项目需要它,那么您可以这样做。
图像数据通常使用BLOB数据类型存储到db中,Room也提供对BLOB数据类型的支持Documentation
您可以如下所述声明实体 class 以存储图像数据。
@Entity(tableName = "test")
public class Test{
@PrimaryKey
@ColumnInfo(name = "_id")
private int id;
@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
private byte[] image;
}
正如 Pinakin 提到的,不建议将图像存储到数据库中,文件路径会更好,但如果需要存储图像,我建议将图像压缩到 2 MB 以下 (here is an example)以避免破坏应用程序。 Room 支持图像的 BLOB。
kotlin 中的实体 class:
ImageTest.kt
@Entity
class ImageTest {
@PrimaryKey(autoGenerate = true)
var id: Int = 1
@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
var data: ByteArray? = null
}
ImageDao.kt
@Dao
interface ImageTestDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun upsertByReplacement(image: List<ImageTest>)
@Query("SELECT * FROM image")
fun getAll(): List<ImageTest>
@Query("SELECT * FROM image WHERE id IN (:arg0)")
fun findByIds(imageTestIds: List<Int>): List<ImageTest>
@Delete
fun delete(imageTest: ImageTest)
}
Databse.kt
import android.arch.persistence.room.Database
import android.arch.persistence.room.RoomDatabase
import android.arch.persistence.room.TypeConverters
@Database(entities = arrayOf(ImageTest::class), version = 1)
@TypeConverters(DataConverters::class)
abstract class Database : RoomDatabase() {
abstract fun getImageTestDao(): ImageTestDao
}
在 DatabaseHelper 中类似
class DatabaseHelper(context: Context) {
init {
DatabaseHelper.context = WeakReference(context)
}
companion object {
private var context: WeakReference<Context>? = null
private const val DATABASE_NAME: String = "image_test_db"
private var singleton: Database? = null
private fun createDatabase(): Database {
return Room.databaseBuilder(context?.get() ?:
throw IllegalStateException("initialize by calling
constructor before calling DatabaseHelper.instance"),
Database::class.java,
DATABASE_NAME)
.build()
}
val instance: Database
@Synchronized get() {
if (null == singleton)
singleton = createDatabase()
return singleton as Database
}
fun setImage(img: Bitmap){
val dao = DatabaseHelper.instance.getImageTestDao()
val imageTest = ImageTest()
imageTest.data = getBytesFromImageMethod(image)//TODO
dao.updsertByReplacement(imageTest)
fun getImage():Bitmap?{
val dao = DatabaseHelper.instance.getImageTestDao()
val imageByteArray = dao.getAll()
return loadImageFromBytes(imageByteArray[0].data)
//change accordingly
}
如果我错了请纠正我。希望这可以帮助那里的人
将图片保存为文件,并将文件路径Uri保存到Room
如 CameraX's image capture 用例所示,成功拍摄照片后,可以安全地检索文件路径引用 Uri savedUri
。
然后Uri可以savedUri.toString()
转成字符串保存到Room
- 如果文件被移动或删除,请务必确保 Room 文件引用也得到更新。
- 保存在 Room 中的图像字符串可能需要转换回 Uri 以使用图像库显示,例如 Glide with
Uri.parse(someString)
。
在 CameraX 示例中,可以在 onImageSaved
中安全地获取图像路径的 Uri。
- 然后使用 Kotlin Coroutines 或 RxJava 将它保存到主线程之外的 Room 中,最好是在 ViewModel 中或处理业务逻辑与视图逻辑分开的地方。
Getting Started with CameraX > 5. Implement ImageCapture use case
private fun takePhoto() {
// Get a stable reference of the modifiable image capture use case
val imageCapture = imageCapture ?: return
// Create time-stamped output file to hold the image
val photoFile = File(
outputDirectory,
SimpleDateFormat(FILENAME_FORMAT, Locale.US
).format(System.currentTimeMillis()) + ".jpg")
// Create output options object which contains file + metadata
val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
// Set up image capture listener, which is triggered after photo has
// been taken
imageCapture.takePicture(
outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback {
override fun onError(exc: ImageCaptureException) {
Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
}
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val savedUri = Uri.fromFile(photoFile)
val msg = "Photo capture succeeded: $savedUri"
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
Log.d(TAG, msg)
}
})
}
Reddit 上的 Saving image in Room database 概述了此策略。
云存储
正在为图片创建文件并将文件路径保存在Room中覆盖本地存储。为了保证图片在多个设备上保存,或者当数据缓存和数据被清除时,需要使用Cloud Storage的形式来上传和下载文件与本地存储同步。
我正在为我的 android 应用程序使用房间持久性库,现在我必须在我的数据库中插入图像。我成功地为原始数据类型定义了@Entity。还通过转换器 class,我存储了所有对象、日期和时间。现在我必须存储图像。我无法理解我们如何定义列信息和实体以及我们如何插入该数据以及从 table.
中读取数据插入单行的最大数据量是多少? Android SQLite 中一个字段中数据的最大和最小大小是多少?
通常不建议将图像数据存储到数据库中。 但是,如果您的项目需要它,那么您可以这样做。
图像数据通常使用BLOB数据类型存储到db中,Room也提供对BLOB数据类型的支持Documentation
您可以如下所述声明实体 class 以存储图像数据。
@Entity(tableName = "test")
public class Test{
@PrimaryKey
@ColumnInfo(name = "_id")
private int id;
@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
private byte[] image;
}
正如 Pinakin 提到的,不建议将图像存储到数据库中,文件路径会更好,但如果需要存储图像,我建议将图像压缩到 2 MB 以下 (here is an example)以避免破坏应用程序。 Room 支持图像的 BLOB。 kotlin 中的实体 class:
ImageTest.kt
@Entity class ImageTest { @PrimaryKey(autoGenerate = true) var id: Int = 1 @ColumnInfo(typeAffinity = ColumnInfo.BLOB) var data: ByteArray? = null }
ImageDao.kt
@Dao interface ImageTestDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun upsertByReplacement(image: List<ImageTest>) @Query("SELECT * FROM image") fun getAll(): List<ImageTest> @Query("SELECT * FROM image WHERE id IN (:arg0)") fun findByIds(imageTestIds: List<Int>): List<ImageTest> @Delete fun delete(imageTest: ImageTest) }
Databse.kt
import android.arch.persistence.room.Database import android.arch.persistence.room.RoomDatabase import android.arch.persistence.room.TypeConverters @Database(entities = arrayOf(ImageTest::class), version = 1) @TypeConverters(DataConverters::class) abstract class Database : RoomDatabase() { abstract fun getImageTestDao(): ImageTestDao }
在 DatabaseHelper 中类似
class DatabaseHelper(context: Context) { init { DatabaseHelper.context = WeakReference(context) } companion object { private var context: WeakReference<Context>? = null private const val DATABASE_NAME: String = "image_test_db" private var singleton: Database? = null private fun createDatabase(): Database { return Room.databaseBuilder(context?.get() ?: throw IllegalStateException("initialize by calling constructor before calling DatabaseHelper.instance"), Database::class.java, DATABASE_NAME) .build() } val instance: Database @Synchronized get() { if (null == singleton) singleton = createDatabase() return singleton as Database } fun setImage(img: Bitmap){ val dao = DatabaseHelper.instance.getImageTestDao() val imageTest = ImageTest() imageTest.data = getBytesFromImageMethod(image)//TODO dao.updsertByReplacement(imageTest) fun getImage():Bitmap?{ val dao = DatabaseHelper.instance.getImageTestDao() val imageByteArray = dao.getAll() return loadImageFromBytes(imageByteArray[0].data) //change accordingly }
如果我错了请纠正我。希望这可以帮助那里的人
将图片保存为文件,并将文件路径Uri保存到Room
如 CameraX's image capture 用例所示,成功拍摄照片后,可以安全地检索文件路径引用 Uri savedUri
。
然后Uri可以savedUri.toString()
转成字符串保存到Room
- 如果文件被移动或删除,请务必确保 Room 文件引用也得到更新。
- 保存在 Room 中的图像字符串可能需要转换回 Uri 以使用图像库显示,例如 Glide with
Uri.parse(someString)
。
在 CameraX 示例中,可以在 onImageSaved
中安全地获取图像路径的 Uri。
- 然后使用 Kotlin Coroutines 或 RxJava 将它保存到主线程之外的 Room 中,最好是在 ViewModel 中或处理业务逻辑与视图逻辑分开的地方。
Getting Started with CameraX > 5. Implement ImageCapture use case
private fun takePhoto() {
// Get a stable reference of the modifiable image capture use case
val imageCapture = imageCapture ?: return
// Create time-stamped output file to hold the image
val photoFile = File(
outputDirectory,
SimpleDateFormat(FILENAME_FORMAT, Locale.US
).format(System.currentTimeMillis()) + ".jpg")
// Create output options object which contains file + metadata
val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
// Set up image capture listener, which is triggered after photo has
// been taken
imageCapture.takePicture(
outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback {
override fun onError(exc: ImageCaptureException) {
Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
}
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val savedUri = Uri.fromFile(photoFile)
val msg = "Photo capture succeeded: $savedUri"
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
Log.d(TAG, msg)
}
})
}
Reddit 上的 Saving image in Room database 概述了此策略。
云存储
正在为图片创建文件并将文件路径保存在Room中覆盖本地存储。为了保证图片在多个设备上保存,或者当数据缓存和数据被清除时,需要使用Cloud Storage的形式来上传和下载文件与本地存储同步。