Sobes.tech
Middle

Πώς μεταφέρουμε σωστά έναν μεγάλο όγκο δεδομένων, όπως μια εικόνα, μεταξύ δραστηριοτήτων στο Android;

sobes.tech AI

Απάντηση από AI

No se recomienda transmitir grandes volúmenes de datos, como una imagen, directamente a través de Intent debido a la limitación en el tamaño de los datos transmitidos durante la serialización (generalmente unos pocos cientos de kilobytes o megabytes). Transmitir datos demasiado grandes puede provocar una TransactionTooLargeException.

Enfoques correctos:

  1. Guardar los datos en un archivo y pasar la ruta del archivo en el Intent.

    • Guardar la imagen en un archivo temporal.
    • Pasar el URI o la ruta del archivo en el Extra del intent.
    • La actividad receptora lee el archivo desde la ruta recibida.
    // Guardar en la primera actividad
    val imageUri: Uri = saveImageToFile(bitmap) // Función para guardar Bitmap en un archivo y devolver Uri
    val intent = Intent(this, SecondActivity::class.java)
    intent.putExtra("image_uri", imageUri.toString())
    startActivity(intent)
    
    // Leer en la segunda actividad
    val imageUriString = intent.getStringExtra("image_uri")
    if (imageUriString != null) {
        val imageUri = Uri.parse(imageUriString)
        val bitmap = loadImageFromFile(imageUri) // Función para cargar Bitmap desde Uri
        imageView.setImageBitmap(bitmap)
    }
    
  2. Usar un Singleton o almacenamiento global de datos.

    • Colocar los datos en un objeto Singleton o en una clase separada accesible desde cualquier parte de la aplicación.
    • No es necesario pasar datos entre actividades, simplemente acceder al Singleton para obtener los datos.
    // Objeto global, por ejemplo, en la clase Application o en un singleton separado
    object DataHolder {
        var bitmap: Bitmap? = null
    }
    
    // En la primera actividad
    DataHolder.bitmap = bitmap
    
    // En la segunda actividad
    val bitmap = DataHolder.bitmap
    imageView.setImageBitmap(bitmap)
    DataHolder.bitmap = null // Limpieza después de usar, si es necesario
    

    Tener en cuenta el ciclo de vida de la aplicación y la actividad que puede ser recreada.

  3. Usar una base de datos (Room) o almacenamiento de datos (por ejemplo, SharedPreferences, aunque no es ideal para imágenes).

    • Guardar la imagen (posiblemente como un array de bytes) en la base de datos.
    • Pasar el identificador del registro en la base de datos a través de Intent.
    • La actividad receptora lee la imagen de la base de datos usando el identificador.
    // Guardar en la primera actividad (pseudo-código para Room)
    val imageEntity = ImageEntity(imageData = bitmapToByteArray(bitmap))
    val imageId = imageDatabase.imageDao().insertImage(imageEntity)
    val intent = Intent(this, SecondActivity::class.java)
    intent.putExtra("image_id", imageId)
    startActivity(intent)
    
    // Leer en la segunda actividad (pseudo-código para Room)
    val imageId = intent.getLongExtra("image_id", -1)
    if (imageId != -1L) {
        val imageEntity = imageDatabase.imageDao().getImageById(imageId)
        if (imageEntity != null) {
            val bitmap = byteArrayToBitmap(imageEntity.imageData)
            imageView.setImageBitmap(bitmap)
        }
    }
    
  4. Usar un ViewModel compartido en Navigation Component.

    • Si se usa Navigation Component, se puede usar un ViewModel compartido asociado con el gráfico de navegación o la actividad.
    • Los datos se colocan en el ViewModel de una actividad y están disponibles para la otra.
    // En el ViewModel
    class SharedViewModel : ViewModel() {
        val imageBitmap = MutableLiveData<Bitmap>()
    }
    
    // En la primera actividad (al usar Navigation Component)
    private val sharedViewModel: SharedViewModel by activityViewModels() // o por navGraphViewModels(R.id.nav_graph)
    sharedViewModel.imageBitmap.value = bitmap
    
    // En la segunda actividad
    private val sharedViewModel: SharedViewModel by activityViewModels() // o por navGraphViewModels(R.id.nav_graph)
    sharedViewModel.imageBitmap.observe(viewLifecycleOwner) { bitmap ->
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap)
        }
    }
    

La elección del método depende del escenario de uso, del tamaño de los datos y de la complejidad de la aplicación. Para imágenes, guardar en un archivo (y pasar la URI) o usar Singleton/ViewModel suele ser la solución más adecuada y eficiente.