Sobes.tech
Middle

Kā pareizi pārsūtīt lielu datu apjomu, piemēram, attēlu, starp aktivitātēm Android?

sobes.tech AI

Atbilde no AI

Liela apjoma datu, piemēram, attēla, tieša pārsūtīšana caur Intent nav ieteicama, jo datu izmēra ierobežojuma dēļ (parasti dažus simtus kilobaitu vai megabaitus). Pārsūtīt pārāk lielus datus var novest pie TransactionTooLargeException.

Pareizie pieejas veidi:

  1. Saglabāt datus failā un pārsūtīt faila ceļu caur Intent.

    • Saglabāt attēlu pagaidu failā.
    • Pārsūtīt URI vai faila ceļu Extra.
    • Saņemamā aktivitāte lasa failu pēc saņemtā ceļa.
    // Pirmās aktivitātes saglabāšana
    val imageUri: Uri = saveImageToFile(bitmap) // Funkcija, kas saglabā Bitmap failā un atgriež URI
    val intent = Intent(this, SecondActivity::class.java)
    intent.putExtra("image_uri", imageUri.toString())
    startActivity(intent)
    
    // Otrās aktivitātes lasīšana
    val imageUriString = intent.getStringExtra("image_uri")
    if (imageUriString != null) {
        val imageUri = Uri.parse(imageUriString)
        val bitmap = loadImageFromFile(imageUri) // Funkcija, kas ielādē Bitmap no URI
        imageView.setImageBitmap(bitmap)
    }
    
  2. Izmantot Singleton vai globālo datu glabātuvi:

    • Datus glabā Singleton objektā vai citā klasē, kas ir pieejama no jebkuras programmas daļas.
    • Starp aktivitātēm nav nepieciešams neko pārsūtīt, vienkārši piekļūstiet Singleton, lai saņemtu datus.
    // Globālais objekts, piemēram, Application klasē vai atsevišķā singleton
    object DataHolder {
        var bitmap: Bitmap? = null
    }
    
    // Pirmās aktivitātes laikā
    DataHolder.bitmap = bitmap
    
    // Otrās aktivitātes laikā
    val bitmap = DataHolder.bitmap
    imageView.setImageBitmap(bitmap)
    DataHolder.bitmap = null // Notīrīt pēc lietošanas, ja nepieciešams
    

    Ir jāņem vērā programmas dzīves cikls un aktivitāte, kura var tikt pārveidota.

  3. Izmantot datu bāzi (Room) vai citu datu glabātuvi (piemēram, SharedPreferences, lai gan attēliem tas nav ideāli):

    • Saglabāt attēlu (iespējams, kā baitu masīvu) datu bāzē.
    • Pārsūtīt datu bāzes ieraksta identifikatoru caur Intent.
    • Saņemamā aktivitāte lasa attēlu no datu bāzes pēc identifikatora.
    // Saglabāšana pirmajā aktivitātē (pseudo-kods 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)
    
    // Lasīšana otrajā aktivitātē (pseudo-kods 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. Izmantot Shared ViewModel Navigation Component-ā:

    • Ja tiek izmantots navigācijas komponents, var izmantot kopīgu ViewModel, kas ir saistīts ar navigācijas grafu vai aktivitāti.
    • Dati tiek glabāti ViewModel vienā aktivitātē un ir pieejami citā.
    // ViewModel
    class SharedViewModel : ViewModel() {
        val imageBitmap = MutableLiveData<Bitmap>()
    }
    
    // Pirmā aktivitāte (ar Navigation Component)
    private val sharedViewModel: SharedViewModel by activityViewModels() // vai by navGraphViewModels(R.id.nav_graph)
    sharedViewModel.imageBitmap.value = bitmap
    
    // Otrā aktivitāte
    private val sharedViewModel: SharedViewModel by activityViewModels() // vai by navGraphViewModels(R.id.nav_graph)
    sharedViewModel.imageBitmap.observe(viewLifecycleOwner) { bitmap ->
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap)
        }
    }
    

Izvēle ir atkarīga no lietošanas scenārija, datu lieluma un sarežģītības. Attēlu glabāšana failā (un URI pārsūtīšana) vai Singleton/ViewModel biežāk ir visefektīvākie un piemērotākie risinājumi.