Sobes.tech
Middle

Kaip teisingai perduoti didelį duomenų kiekį, pavyzdžiui, vaizdą, tarp veiklų Android?

sobes.tech AI

Atsakymas iš AI

Didelės apimties duomenų, tokių kaip vaizdas, perdavimas tiesiogiai per Intent nerekomenduojamas dėl duomenų dydžio apribojimo, kuris dažniausiai yra keli šimtai kilobaitų ar megabaitų. Per didelių duomenų perdavimas gali sukelti TransactionTooLargeException.

Tinkami būdai:

  1. Išsaugoti duomenis faile ir perduoti failo kelią per Intent.

    • Išsaugoti vaizdą laikinuose failuose.
    • Perduoti URI arba failo kelią Extra.
    • Priimančioji aktyvumas skaito failą pagal gautą kelią.
    // Pirmoje aktyvumo dalyje išsaugojimas
    val imageUri: Uri = saveImageToFile(bitmap) // Funkcija, išsauganti Bitmap į failą ir grąžinanti Uri
    val intent = Intent(this, SecondActivity::class.java)
    intent.putExtra("image_uri", imageUri.toString())
    startActivity(intent)
    
    // Antroje aktyvumo dalyje skaitymas
    val imageUriString = intent.getStringExtra("image_uri")
    if (imageUriString != null) {
        val imageUri = Uri.parse(imageUriString)
        val bitmap = loadImageFromFile(imageUri) // Funkcija, skaitanti Bitmap iš Uri
        imageView.setImageBitmap(bitmap)
    }
    
  2. Naudoti Singleton arba globalų duomenų saugyklą:

    • Duomenys saugomi Singleton objekte arba kitame klasėje, kuris yra pasiekiamas iš bet kurios programos dalies.
    • Tarp aktyvumų nieko perduoti nereikia, tiesiog kreipiamasi į Singleton duomenų gavimui.
    // Globalus objektas, pavyzdžiui, Application klasėje arba atskirame singleton'e
    object DataHolder {
        var bitmap: Bitmap? = null
    }
    
    // Pirmoje aktyvumo dalyje
    DataHolder.bitmap = bitmap
    
    // Antroje aktyvumo dalyje
    val bitmap = DataHolder.bitmap
    imageView.setImageBitmap(bitmap)
    DataHolder.bitmap = null // Valymas po naudojimo, jei reikia
    

    Reikia atsižvelgti į programos gyvavimo ciklą ir aktyvumą, kuris gali būti perkurtas.

  3. Naudoti duomenų bazę (Room) arba kitą saugyklą (pavyzdžiui, SharedPreferences, nors vaizdams tai nėra idealu):

    • Išsaugoti vaizdą (galbūt kaip baitų masyvą) duomenų bazėje.
    • Perduoti įrašo identifikatorių per Intent.
    • Priimanti aktyvumas skaito vaizdą iš duomenų bazės pagal identifikatorių.
    // Pirmoje aktyvumo dalyje išsaugojimas (pseudo-kodas 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)
    
    // Antroje aktyvumo dalyje skaitymas (pseudo-kodas 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. Naudoti Shared ViewModel Navigation Component-ą:

    • Jei naudojama Navigation komponentas, galima naudoti bendrą ViewModel, kuris susietas su navigacijos grafu arba aktyvumu.
    • Duomenys saugomi ViewModel ir yra prieinami kitai aktyvacijai.
    // ViewModel klasėje
    class SharedViewModel : ViewModel() {
        val imageBitmap = MutableLiveData<Bitmap>()
    }
    
    // Pirmoje aktyvumo dalyje (naudojant Navigation Component)
    private val sharedViewModel: SharedViewModel by activityViewModels() // arba by navGraphViewModels(R.id.nav_graph)
    sharedViewModel.imageBitmap.value = bitmap
    
    // Antroje aktyvumo dalyje
    private val sharedViewModel: SharedViewModel by activityViewModels() // arba by navGraphViewModels(R.id.nav_graph)
    sharedViewModel.imageBitmap.observe(viewLifecycleOwner) { bitmap ->
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap)
        }
    }
    

Pasirinkimas priklauso nuo naudojimo scenarijaus, duomenų dydžio ir sudėtingumo. Vaizdų saugojimas faile (ir URI perdavimas) arba Singleton/ViewModel dažniausiai yra efektyviausi ir tinkamiausi sprendimai.