Jak poprawnie przesłać dużą ilość danych, na przykład obraz, między aktywnościami w Android?
sobes.tech AI
Odpowiedź od AI
Nie zaleca się przesyłania dużych ilości danych, takich jak obraz, bezpośrednio przez Intent ze względu na ograniczenie rozmiaru danych przesyłanych podczas serializacji (zwykle kilka setek kilobajtów lub megabajtów). Przesyłanie zbyt dużych danych może spowodować TransactionTooLargeException.
Poprawne podejścia:
-
Zapisz dane do pliku i przekaż ścieżkę do pliku w
Intent.- Zapisz obraz do tymczasowego pliku.
- Przekaż URI lub ścieżkę do pliku w
Extraintencji. - Odbierająca aktywność odczytuje plik z otrzymanej ścieżki.
// W pierwszej aktywności val imageUri: Uri = saveImageToFile(bitmap) // Funkcja zapisująca Bitmap do pliku i zwracająca Uri val intent = Intent(this, SecondActivity::class.java) intent.putExtra("image_uri", imageUri.toString()) startActivity(intent) // W drugiej aktywności val imageUriString = intent.getStringExtra("image_uri") if (imageUriString != null) { val imageUri = Uri.parse(imageUriString) val bitmap = loadImageFromFile(imageUri) // Funkcja ładująca Bitmap z Uri imageView.setImageBitmap(bitmap) } -
Użyj Singletona lub globalnego magazynu danych.
- Umieść dane w Singletonie lub w osobnej klasie dostępnej z każdego miejsca w aplikacji.
- Nie trzeba nic przekazywać między aktywnościami, wystarczy odwołać się do Singletona, aby uzyskać dane.
// Globalny obiekt, np. w klasie Application lub w osobnym singletonie object DataHolder { var bitmap: Bitmap? = null } // W pierwszej aktywności DataHolder.bitmap = bitmap // W drugiej aktywności val bitmap = DataHolder.bitmap imageView.setImageBitmap(bitmap) DataHolder.bitmap = null // Czyszczenie po użyciu, jeśli konieczneNależy uwzględnić cykl życia aplikacji i aktywności, które mogą być odtwarzane.
-
Użyj bazy danych (Room) lub innego magazynu danych (np. SharedPreferences, choć nie jest to idealne dla obrazów).
- Zapisz obraz (może w formie tablicy bajtów) w bazie danych.
- Przekaż identyfikator wpisu w bazie danych przez
Intent. - Aktywność odbiorcza odczytuje obraz z bazy danych za pomocą identyfikatora.
// Zapis w pierwszej aktywności (pseudokod dla 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) // Odczyt w drugiej aktywności (pseudokod dla 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) } } -
Użyj wspólnego ViewModel w Navigation Component.
- Jeśli używasz Navigation Component, możesz użyć wspólnego
ViewModel, powiązanego z grafem nawigacji lub aktywnością. - Dane są umieszczane w
ViewModeljednej aktywności i dostępne w innej.
// W ViewModel class SharedViewModel : ViewModel() { val imageBitmap = MutableLiveData<Bitmap>() } // W pierwszej aktywności (z Navigation Component) private val sharedViewModel: SharedViewModel by activityViewModels() // lub przez navGraphViewModels(R.id.nav_graph) sharedViewModel.imageBitmap.value = bitmap // W drugiej aktywności private val sharedViewModel: SharedViewModel by activityViewModels() // lub przez navGraphViewModels(R.id.nav_graph) sharedViewModel.imageBitmap.observe(viewLifecycleOwner) { bitmap -> if (bitmap != null) { imageView.setImageBitmap(bitmap) } } - Jeśli używasz Navigation Component, możesz użyć wspólnego
Wybór metody zależy od scenariusza użycia, rozmiaru danych i złożoności aplikacji. Dla obrazów, zapis do pliku (i przekazanie URI) lub użycie Singletona/ViewModel jest najczęściej najbardziej odpowiednie i wydajne.