如何在室内持久性库中插入图像?

Pri*_*mar 18 sqlite android android-sqlite android-room

我正在为我的android应用程序使用房间持久性库,现在我必须在我的数据库中插入图像.我成功地为原始数据类型定义了@Entity.并且还通过转换器类,我存储了所有对象,日期,时间.现在我必须存储Image.我无法理解我们如何定义列信息和实体以及我们如何插入数据以及从表中读取数据.

插入单行的数据的最大大小是多少?Android SQLite中一个字段中数据的最大和最小大小是多少?

Pin*_*kin 28

通常不建议将图像数据存储到数据库中.但是,如果您的项目需要它,那么您可以这样做.

图像数据通常使用BLOB数据类型存储到db中,Room还提供对BLOB数据类型文档的支持

您可以如下所述声明您的实体类来存储图像数据.

@Entity(tableName = "test")
public class Test{

@PrimaryKey
@ColumnInfo(name = "_id")
private int id;

@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
private byte[] image;
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢它的工作。我需要添加编码器和解码器,将原始图像转换为 byte[] 并将 byte[] 转换为原始图像 (2认同)

Ada*_*itz 10

将图像保存为文件,并将文件路径Uri保存到Room

CameraX图像捕获用例中可以看出,成功拍摄照片后,savedUri可以安全地检索文件路径引用 Uri, 。

然后,可以使用 , 将 Uri 转换为字符串savedUri.toString(),并保存到 Room。

  • 如果文件被移动或删除,请确保 Room 文件引用也得到更新,这一点很重要。
  • Room 中保存的图像字符串可能需要转换回 Uri,才能通过图像库(例如 Glide with)显示Uri.parse(someString)

在 CameraX 示例中,可以安全地在 中获取图像路径的 Uri onImageSaved

  • 然后,使用 Kotlin Coroutines 或 RxJava 将其保存到主线程之外的 Room 中,最好保存在 ViewModel 中或处理与视图逻辑分开的业务逻辑的地方。

CameraX 入门 > 5. 实施 ImageCapture 用例

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)
           }
       })
}
Run Code Online (Sandbox Code Playgroud)

Reddit 上的将图像保存到 Room 数据库中概述了此策略。

云储存

为图像创建文件并将文件路径保存在 Room 中,覆盖本地存储。为了确保图像在多个设备上保存,或者当数据缓存和数据被清除时,需要一种云存储的形式来将文件上传到本地存储以及下载并与本地存储同步。


adi*_*ddy 8

正如Pinakin所提到的,不建议将图像存储到数据库中,文件路径会更好,但如果需要存储图像,我建议将图像压缩到2 MB以下(这是一个示例)以避免破坏应用程序.房间支持BLOB图像.kotlin中的实体类:

ImageTest.kt

 @Entity    
 class ImageTest {

        @PrimaryKey(autoGenerate = true)

        var id: Int = 1

        @ColumnInfo(typeAffinity = ColumnInfo.BLOB)
        var data: ByteArray? = null
      }
Run Code Online (Sandbox Code Playgroud)

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)
   }
Run Code Online (Sandbox Code Playgroud)

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
   }
Run Code Online (Sandbox Code Playgroud)

在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 
     }
Run Code Online (Sandbox Code Playgroud)

如果我错了,请纠正我.希望这有助于那里的人