Sobes.tech
Middle

Come trasferire correttamente una grande quantità di dati, come un'immagine, tra le attività in Android?

sobes.tech AI

Risposta dell'AI

Non è consigliabile trasferire grandi volumi di dati, come immagini, direttamente tramite Intent a causa del limite di dimensione dei dati trasmessi durante la serializzazione (solitamente qualche centinaio di kilobyte o megabyte). Il trasferimento di dati troppo grandi può portare a una TransactionTooLargeException.

Approcci corretti:

  1. Salvare i dati in un file e passare il percorso del file in Intent.

    • Salvare l’immagine in un file temporaneo.
    • Passare l’URI o il percorso del file nell’Extra dell’intent.
    • L’attività ricevente legge il file dal percorso ricevuto.
    // In prima attività
    val imageUri: Uri = saveImageToFile(bitmap) // Funzione per salvare il Bitmap in un file e restituire l’Uri
    val intent = Intent(this, SecondActivity::class.java)
    intent.putExtra("image_uri", imageUri.toString())
    startActivity(intent)
    
    // In seconda attività
    val imageUriString = intent.getStringExtra("image_uri")
    if (imageUriString != null) {
        val imageUri = Uri.parse(imageUriString)
        val bitmap = loadImageFromFile(imageUri) // Funzione per caricare il Bitmap dall’Uri
        imageView.setImageBitmap(bitmap)
    }
    
  2. Usare Singleton o storage globale di dati.

    • Inserire i dati in un oggetto Singleton o in una classe separata accessibile da qualsiasi punto dell’app.
    • Non è necessario passare nulla tra le attività, basta accedere al Singleton per ottenere i dati.
    // Oggetto globale, ad esempio, nella classe Application o in un singleton separato
    object DataHolder {
        var bitmap: Bitmap? = null
    }
    
    // In prima attività
    DataHolder.bitmap = bitmap
    
    // In seconda attività
    val bitmap = DataHolder.bitmap
    imageView.setImageBitmap(bitmap)
    DataHolder.bitmap = null // Pulizia dopo l’uso, se necessario
    

    È importante considerare il ciclo di vita dell’applicazione e dell’attività, che può essere ricreata.

  3. Usare un database (Room) o un’altra soluzione di storage (ad esempio SharedPreferences, anche se non ideale per le immagini).

    • Salvare l’immagine (possibilmente come array di byte) nel database.
    • Passare l’identificatore del record nel database tramite Intent.
    • L’attività ricevente legge l’immagine dal database usando l’identificatore.
    // Salvataggio in prima attività (pseudocodice per 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)
    
    // Lettura in seconda attività (pseudocodice per 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. Usare un ViewModel condiviso nel Navigation Component.

    • Se si utilizza il componente di navigazione, si può usare un ViewModel condiviso legato al grafo di navigazione o all’attività.
    • I dati vengono inseriti nel ViewModel di una attività e sono accessibili dall’altra.
    // Nel ViewModel
    class SharedViewModel : ViewModel() {
        val imageBitmap = MutableLiveData<Bitmap>()
    }
    
    // Nella prima attività (con Navigation Component)
    private val sharedViewModel: SharedViewModel by activityViewModels() // o con navGraphViewModels(R.id.nav_graph)
    sharedViewModel.imageBitmap.value = bitmap
    
    // Nella seconda attività
    private val sharedViewModel: SharedViewModel by activityViewModels() // o con navGraphViewModels(R.id.nav_graph)
    sharedViewModel.imageBitmap.observe(viewLifecycleOwner) { bitmap ->
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap)
        }
    }
    

La scelta del metodo dipende dallo scenario d’uso, dalla dimensione dei dati e dalla complessità dell’app. Per le immagini, salvare in un file (e passare l’URI) o usare Singleton/ViewModel sono soluzioni più adatte ed efficienti.