Como transmitir corretamente uma grande quantidade de dados, como uma imagem, entre atividades no Android?
sobes.tech IA
Resposta da IA
Não é recomendado transferir grandes volumes de dados, como imagens, diretamente através de Intent devido à limitação no tamanho dos dados transmitidos durante a serialização (normalmente alguns centenas de quilobytes ou megabytes). A transferência de dados demasiado grandes pode levar a uma TransactionTooLargeException.
Abordagens corretas:
-
Guardar os dados num ficheiro e passar o caminho do ficheiro no
Intent.- Guardar a imagem num ficheiro temporário.
- Passar o URI ou caminho do ficheiro no
Extrado intent. - A atividade receptora lê o ficheiro a partir do caminho recebido.
// Guardar na primeira atividade val imageUri: Uri = saveImageToFile(bitmap) // Função para guardar o Bitmap num ficheiro e devolver Uri val intent = Intent(this, SecondActivity::class.java) intent.putExtra("image_uri", imageUri.toString()) startActivity(intent) // Ler na segunda atividade val imageUriString = intent.getStringExtra("image_uri") if (imageUriString != null) { val imageUri = Uri.parse(imageUriString) val bitmap = loadImageFromFile(imageUri) // Função para carregar o Bitmap a partir do Uri imageView.setImageBitmap(bitmap) } -
Usar Singleton ou armazenamento global de dados.
- Colocar os dados num objeto Singleton ou numa classe separada acessível de qualquer parte da aplicação.
- Não é necessário passar nada entre atividades, basta aceder ao Singleton para obter os dados.
// Objeto global, por exemplo, na classe Application ou num singleton separado object DataHolder { var bitmap: Bitmap? = null } // Na primeira atividade DataHolder.bitmap = bitmap // Na segunda atividade val bitmap = DataHolder.bitmap imageView.setImageBitmap(bitmap) DataHolder.bitmap = null // Limpeza após uso, se necessárioÉ importante considerar o ciclo de vida da aplicação e da atividade, que pode ser recriada.
-
Usar base de dados (Room) ou armazenamento de dados (por exemplo, SharedPreferences, embora não seja ideal para imagens).
- Guardar a imagem (possivelmente em forma de array de bytes) na base de dados.
- Passar o identificador do registo na base de dados através de
Intent. - A atividade receptora lê a imagem da base de dados usando o identificador.
// Guardar na primeira atividade (pseudocó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) // Ler na segunda atividade (pseudocó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) } } -
Usar ViewModel compartilhado no Navigation Component.
- Se estiver usando o componente de navegação, pode usar um
ViewModelcomum ligado ao grafo de navegação ou à atividade. - Os dados são colocados no
ViewModelde uma atividade e acessíveis em outra.
// No ViewModel class SharedViewModel : ViewModel() { val imageBitmap = MutableLiveData<Bitmap>() } // Na primeira atividade (usando Navigation Component) private val sharedViewModel: SharedViewModel by activityViewModels() // ou por navGraphViewModels(R.id.nav_graph) sharedViewModel.imageBitmap.value = bitmap // Na segunda atividade private val sharedViewModel: SharedViewModel by activityViewModels() // ou por navGraphViewModels(R.id.nav_graph) sharedViewModel.imageBitmap.observe(viewLifecycleOwner) { bitmap -> if (bitmap != null) { imageView.setImageBitmap(bitmap) } } - Se estiver usando o componente de navegação, pode usar um
A escolha do método depende do cenário de uso, do tamanho dos dados e da complexidade da aplicação. Para imagens, guardar em ficheiro (e passar o URI) ou usar Singleton/ViewModel costuma ser as soluções mais adequadas e eficientes.