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:
-
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) } -
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 reikiaReikia atsižvelgti į programos gyvavimo ciklą ir aktyvumą, kuris gali būti perkurtas.
-
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) } } -
Naudoti Shared ViewModel Navigation Component-ą:
- Jei naudojama Navigation komponentas, galima naudoti bendrą
ViewModel, kuris susietas su navigacijos grafu arba aktyvumu. - Duomenys saugomi
ViewModelir 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) } } - Jei naudojama Navigation komponentas, galima naudoti bendrą
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.