Wie füge ich ein Bild in die Raumpersistenzbibliothek ein?

Lesezeit: 6 Minuten

Ich verwende die Raumpersistenzbibliothek für meine Android-Anwendung. Jetzt muss ich ein Bild in meine Datenbank einfügen. Ich definiere erfolgreich @Entity für den primitiven Datentyp. und auch durch die Konverterklasse habe ich alle Objekte, Datum und Uhrzeit gespeichert. Jetzt muss ich Image speichern. Ich kann nicht verstehen, wie wir Spalteninformationen und Entitäten definieren und wie wir diese Daten einfügen und Daten aus der Tabelle lesen.

Was ist die maximale Größe der Daten, die in die einzelne Zeile eingefügt werden? Was ist die maximale und minimale Größe von Daten in einem Feld in Android SQLite?

  • Sie können Blob verwenden, um Bilder in Room zu speichern.

    – Reena

    21. September 2017 um 7:14 Uhr

  • Folge dies developer.android.com/topic/libraries/architecture/room.html

    – Ankita

    21. September 2017 um 7:18 Uhr

  • @CommonsWare Was schlagen Sie vor, wenn Sie nicht empfehlen, Bilder in der Datenbank zu speichern? Bilder im externen Speicher speichern?

    – Aniruddha

    21. Februar 2018 um 19:36 Uhr

  • @Aniruddha: Ob Sie verwenden interne Speicher oder externer Speicher hängt davon ab, ob der Benutzer unabhängigen Zugriff auf die Bilder benötigt.

    – CommonsWare

    21. Februar 2018 um 19:50 Uhr

  • @CommonsWare Wäre für Lernzwecke am besten, wenn Sie erklären könnten, warum Sie nicht empfehlen, das Bild in der Datenbank zu speichern.

    – Aniruddha

    22. Februar 2018 um 5:10 Uhr

Es wird normalerweise nicht empfohlen, Bilddaten in der Datenbank zu speichern. Wenn es jedoch für Ihr Projekt erforderlich ist, können Sie dies tun.

Bilddaten werden normalerweise unter Verwendung des BLOB-Datentyps in db gespeichert, Room bietet auch Unterstützung für den BLOB-Datentyp Dokumentation

Sie können Ihre Entitätsklasse wie unten erwähnt deklarieren, um Bilddaten zu speichern.

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

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

@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
private byte[] image;
}

  • Danke, es funktioniert. Ich muss Encoder und Decoder hinzufügen, die das Rohbild in Byte konvertieren[] und byte[] zum Rohbild

    – Prinz Kumar

    6. November 2017 um 9:52 Uhr

  • @PrinceKumar True, Sie benötigen Encoder und Decoder für Bitmap zu Byte[] und umgekehrt.

    – Pinakin Kansara

    22. Februar 2018 um 5:52 Uhr

  • Ich kann den Blob-Typ nicht verwenden?

    – Jhon Fredy Trujillo Ortega

    7. März 2018 um 17:03 Uhr

  • @JhonFredyTrujilloOrtega, Wenn Sie dann kein Blob verwenden möchten, komprimieren Sie zuerst Ihr Bild, konvertieren Sie es dann in eine “Base 64” -Zeichenfolge und speichern Sie es in db. Das Speichern von „blob“ oder „base 64“ wird nicht empfohlen. Am besten speichern Sie die Datei lokal im Dateisystem und fügen nur einen Referenzeintrag in db hinzu. es liegt jedoch an Ihrer Anforderung.

    – Pinakin Kansara

    13. März 2018 um 5:10 Uhr

  • Es scheint, als würde diese Lösung BLOB nicht wirklich verwenden. Diese Lösung sorgt dafür, dass die App das Byte-Array vollständig im Speicher hält, während eine echte Verwendung von BLOB, wie z. B. in SQLite oder MySQL, InputStream zum Schreiben und OutputStream zum Schreiben verwenden würde. Wenn also das Byte-Array zu groß ist, wird jeweils nur ein Puffer davon im Speicher gehalten. Übrigens unterstützt BitmapFactory das Arbeiten mit InputStream. Fehlt diese Funktion in der ROOM-Datenbank?

    – Elad Lavi

    28. April 2018 um 5:23 Uhr

Benutzeravatar von adithya reddy
Adithya Reddy

Wie Pinakin erwähnte, wird es nicht empfohlen, ein Bild in einer Datenbank zu speichern, und der Dateipfad wäre besser, aber wenn es erforderlich ist, ein Bild zu speichern, würde ich vorschlagen, das Bild auf unter 2 MB zu komprimieren (hier ist ein Beispiel), um eine Beschädigung der App zu vermeiden. Room unterstützt BLOB für Bilder. Entitätsklasse in kotlin:

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)
   }

Datenbank.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
   }
    

In DatabaseHelper so etwas wie

  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 
     }

Korrigiere mich, wenn ich falsch liege. Hoffe, das hilft jemandem da draußen

  • Vielen Dank für die Erklärung jeder Zeile und die leicht verständliche Lösung meines gesamten Projekts in Java.

    – Prinz Kumar

    6. November 2017 um 9:51 Uhr

Benutzeravatar von AdamHurwitz
AdamHurwitz

Speichern Sie das Bild als Datei und speichern Sie den Dateipfad Uri in Room

Wie in … gesehen KameraX‘s Bilderfassung Anwendungsfall, wenn ein Foto erfolgreich aufgenommen wurde, die Dateipfadreferenz Uri, savedUrikann sicher abgerufen werden.

Anschließend kann der Uri mit in einen String umgewandelt werden savedUri.toString()und in Raum gespeichert.

  • Es ist wichtig sicherzustellen, dass die Room-Dateireferenz auch aktualisiert wird, wenn die Datei verschoben oder gelöscht wird.
  • Die in Room gespeicherte Bildzeichenfolge muss möglicherweise wieder in einen Uri konvertiert werden, um mit einer Bildbibliothek wie Glide with angezeigt zu werden Uri.parse(someString).

Im CameraX-Beispiel kann der Uri eines Bildpfads sicher abgerufen werden onImageSaved.

  • Es würde dann mit Kotlin Coroutines oder RxJava aus dem Haupt-Thread in Room gespeichert, vorzugsweise in einem ViewModel oder an einem Ort, der die Geschäftslogik getrennt von der Ansichtslogik behandelt.

Erste Schritte mit CameraX > 5. Implementieren Sie den ImageCapture-Anwendungsfall

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)
           }
       })
}

Diese Strategie ist in skizziert Bild in der Raumdatenbank speichern auf reddit.

Cloud-Speicher

Das Erstellen einer Datei für das Bild und das Speichern des Dateipfads in Room deckt den lokalen Speicher ab. Um sicherzustellen, dass die Bilder auf mehreren Geräten gespeichert werden oder wenn der Datencache und die Daten gelöscht werden, wird eine Form von Cloud-Speicher wird benötigt, um die Dateien in den lokalen Speicher hochzuladen und herunterzuladen und mit ihm zu synchronisieren.

1431910cookie-checkWie füge ich ein Bild in die Raumpersistenzbibliothek ein?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy