将项目添加到列表时,mutableLiveData 不会触发重组

问题描述 投票:0回答:1

我在 viewModel 中得到了一个封装在可变 LiveData 中的位图列表,我正在从在线数据库中提取位图,并在它们到达时将它们添加到列表中。由于某种原因,当我更新列表时它不会触发重组。我什至尝试在列表中调用“postvalue”,但仍然不起作用。

package com.example.firebasetests

import android.content.ContentValues.TAG
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.firebasetests.ui.theme.FirebasetestsTheme
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import androidx.compose.runtime.livedata.observeAsState
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.firebase.ui.auth.AuthUI
import com.firebase.ui.auth.FirebaseAuthUIActivityResultContract
import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.actionCodeSettings
import com.google.firebase.auth.ktx.auth
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.storage.StorageReference
import com.google.firebase.storage.ktx.storage
import java.io.ByteArrayOutputStream
import com.google.firebase.storage.component1
import com.google.firebase.storage.component2
import androidx.compose.runtime.*
import androidx.compose.foundation.lazy.items
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import kotlinx.coroutines.flow.MutableStateFlow

class MainActivity : ComponentActivity() {
    private lateinit var auth: FirebaseAuth
    // See: https://developer.android.com/training/basics/intents/result
    private val signInLauncher = registerForActivityResult(
        FirebaseAuthUIActivityResultContract(),
    ) { res ->
        this.onSignInResult(res)
    }
    // Choose authentication providers
    val providers = arrayListOf(
        AuthUI.IdpConfig.EmailBuilder().build(),
        AuthUI.IdpConfig.PhoneBuilder().build(),
        AuthUI.IdpConfig.GoogleBuilder().build(),
       // AuthUI.IdpConfig.E
    )

    private fun onSignInResult(result: FirebaseAuthUIAuthenticationResult) {
        val response = result.idpResponse
        if (result.resultCode == RESULT_OK) {
            // Successfully signed in
            val user = FirebaseAuth.getInstance().currentUser
            // ...
        } else {
            // Sign in failed. If response is null the user canceled the
            // sign-in flow using the back button. Otherwise check
            // response.getError().getErrorCode() and handle the error.
            // ...
        }
    }

    val viewModel = FeedUIViewModel()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            FirebasetestsTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    val db = Firebase.firestore
                    auth = Firebase.auth

                    MyApp(db, viewModel)

                    val storage = Firebase.storage

                    var storageRef = storage.reference
                    var imageRef: StorageReference = storageRef.child("baloo.png")


                    val pepeRef = storageRef.child("pepe.jpg")
                    val pepe = BitmapFactory.decodeResource(resources,R.raw.pepe)
                    val baos = ByteArrayOutputStream()
                    pepe.compress(Bitmap.CompressFormat.JPEG, 100, baos)
                    val data = baos.toByteArray()
                    var uploadTask = pepeRef.putBytes(data)
                    uploadTask.addOnFailureListener{

                    }.addOnSuccessListener {

                    }


                    val ONE_MEGABYTE: Long = 1024 * 1024
                    storageRef.listAll()
                        .addOnSuccessListener { (items, prefixes) ->
                            for (prefix in prefixes) {

                                // All the prefixes under listRef.
                                // You may call listAll() recursively on them.
                            }

                            for (item in items) {
                                // All the items under listRef.
                                val itemRef = storageRef.child(item.name)
                                itemRef.getBytes(ONE_MEGABYTE).addOnSuccessListener {imageBytes ->
                                    // Convert byte array to bitmap
                                    val bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)

                                    viewModel.profileImages.value?.add(bitmap)
                                    viewModel.profileImages.postValue(viewModel.profileImages.value)
                                //Log.d("MYTAG",""+viewModel.profileImages.value?.size)
                                }
                            }
                        }
                        .addOnFailureListener {
                            // Uh-oh, an error occurred!
                        }



                    imageRef.getBytes(ONE_MEGABYTE).addOnSuccessListener {imageBytes ->
                        // Convert byte array to bitmap
                        val bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
                        //viewModel.image.value = bitmap
                        // Data for "images/island.jpg" is returned, use this as needed
                        Log.d("MYTAG","got image")

                    }.addOnFailureListener {
                        // Handle any errors
                    }

                    // Create and launch sign-in intent
                    /*
                    val signInIntent = AuthUI.getInstance()
                        .createSignInIntentBuilder()
                        .setAvailableProviders(providers)
                        .build()
                    signInLauncher.launch(signInIntent)
                     */
                }
            }
        }
    }
}


class FeedUIViewModel: ViewModel(){
    var image:  MutableLiveData<Bitmap> = MutableLiveData()
    var profileImages: MutableLiveData<MutableList<Bitmap>> = MutableLiveData(mutableListOf<Bitmap>())
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyApp(db: FirebaseFirestore, viewModel: FeedUIViewModel) {
    var text by remember { mutableStateOf("") }
    var clickedText by remember{ mutableStateOf("") }
    val emptyBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)
    emptyBitmap.eraseColor(Color.BLUE)
    val image by viewModel.image.observeAsState(emptyBitmap)
    val profiles by viewModel.profileImages.observeAsState()
    
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        // Text Entry Field
        TextField(
            value = text,
            onValueChange = {
                text = it
            },
            label = { Text("Label") }
        )

        // Button to the right of the text entry field
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(8.dp),
            horizontalArrangement = Arrangement.End
        ) {
            Button(
                onClick = {
                    clickedText = text
                    // Create a new user with a first and last name
                    val string = hashMapOf(
                        "string" to text,
                    )

                    // Add a new document with a generated ID
                    db.collection("users").document("chat1")
                        .set(string)
                        .addOnSuccessListener { documentReference ->
                            Log.d("BIGTAG", "DocumentSnapshot added with ID: $documentReference")
                        }
                        .addOnFailureListener { e ->
                            Log.w("BIGTAG", "Error adding document", e)
                        }
                },
                modifier = Modifier
                    .wrapContentWidth()
            ) {
                Text("Display Text")
            }
        }

        // Text Display Field
        Text(
            text = clickedText,
            modifier = Modifier
                .fillMaxWidth()
                .padding(8.dp)
        )

        LazyColumn{
            items(profiles!!){ profilePic->
                Image(
                    bitmap = profilePic.asImageBitmap(),
                    contentDescription = null, // Content description for accessibility
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(200.dp) // Adjust the height as needed
                        .padding(16.dp)
                )

            }
        }


/*
        Image(
            painter = BitmapPainter(image.asImageBitmap()),
            contentDescription = null,
            modifier = Modifier
                .fillMaxWidth()
                .size(200.dp) // Adjust the size as needed
        )
*/



    }
}
android kotlin android-jetpack-compose android-jetpack mutablelivedata
1个回答
0
投票

刚刚找到解决方案,我没有正确更新 mutableLiveData:

viewModel.profileImages.value = (viewModel.profileImages.value ?: mutableListOf()).toMutableList().apply {
    add(bitmap)
}
© www.soinside.com 2019 - 2024. All rights reserved.