最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

android - How to update arraylist in jetpack compose - Stack Overflow

programmeradmin1浏览0评论

I'm stuck trying to understand how to get a variable initialised, and later updated, in kotlin to update in Jetpack Compose and cause a composition that uses it to recompose. The variable is an arraylist of bitmaps set up like so (all of this works fine so I have not included the getOutputDirectory() and imageReaderNew() functions):

// set up an empty bitmaps arraylist
// should I be using mutableListOf() here? if so how?
var bitmaps: ArrayList<Bitmap> = ArrayList()

// get the uri of the folder to save images to
val outputDirectory = getOutputDirectory()

// read in a list of images in the images folder
var fileList: ArrayList<File> = imageReaderNew(outputDirectory)

// get a list of bitmaps of the images
bitmaps = getBitmapList(fileList)

When I initialise my composition I do this:

BottomSheetScaffold(
    scaffoldState = scaffoldState,
    sheetPeekHeight = 0.dp,
    sheetContent = {
        PhotoBottomSheetContent(
            bitmaps = bitmaps,
            //should I be using remember here?
            //bitmaps = remember { bitmaps },
            modifier = Modifier.fillMaxWidth()
        )
   }
)
{ }

Finally, in my composable I do this:

fun PhotoBottomSheetContent(
    bitmaps: List<Bitmap>,
    // should I be using mutableListOf() or remember { } here? again if so how?
    modifier: Modifier = Modifier
)
{
}

I'm stuck trying to understand how to get a variable initialised, and later updated, in kotlin to update in Jetpack Compose and cause a composition that uses it to recompose. The variable is an arraylist of bitmaps set up like so (all of this works fine so I have not included the getOutputDirectory() and imageReaderNew() functions):

// set up an empty bitmaps arraylist
// should I be using mutableListOf() here? if so how?
var bitmaps: ArrayList<Bitmap> = ArrayList()

// get the uri of the folder to save images to
val outputDirectory = getOutputDirectory()

// read in a list of images in the images folder
var fileList: ArrayList<File> = imageReaderNew(outputDirectory)

// get a list of bitmaps of the images
bitmaps = getBitmapList(fileList)

When I initialise my composition I do this:

BottomSheetScaffold(
    scaffoldState = scaffoldState,
    sheetPeekHeight = 0.dp,
    sheetContent = {
        PhotoBottomSheetContent(
            bitmaps = bitmaps,
            //should I be using remember here?
            //bitmaps = remember { bitmaps },
            modifier = Modifier.fillMaxWidth()
        )
   }
)
{ }

Finally, in my composable I do this:

fun PhotoBottomSheetContent(
    bitmaps: List<Bitmap>,
    // should I be using mutableListOf() or remember { } here? again if so how?
    modifier: Modifier = Modifier
)
{
}
Share Improve this question asked Jan 31 at 19:15 garrettlynchirlgarrettlynchirl 91011 silver badges24 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 2

The way you're doing it doesn’t work because Jetpack Compose doesn’t automatically track changes to regular variables like ArrayList. Compose only recomposes when it detects changes to state objects it’s explicitly observing (like mutableStateOf or mutableStateListOf). Since bitmaps is just a plain ArrayList, updating it won’t trigger recomposition.

To make Compose track changes to bitmaps and trigger recomposition, you need to wrap it in a Compose state. Here’s how:

Use mutableStateListOf to ensures Compose tracks changes to individual items (adding/removing items):

val bitmaps = remember { mutableStateListOf<Bitmap>() }

Use LaunchedEffect to load bitmaps without blocking the UI. Update the state when the data is ready:

LaunchedEffect(Unit) {
    val outputDirectory = getOutputDirectory()
    val fileList = imageReaderNew(outputDirectory)
    val loadedBitmaps = getBitmapList(fileList)
    
    bitmaps.clear()
    bitmaps.addAll(loadedBitmaps) 
}

Pass the state to your composable. No need for remember here—Compose will automatically observe the state:

BottomSheetScaffold(
    sheetContent = {
        PhotoBottomSheetContent(bitmaps = bitmaps)
    }
)

In PhotoBottomSheetContent, use the bitmaps list as usual. It will automatically recompose when the state changes:

@Composable
fun PhotoBottomSheetContent(bitmaps: List<Bitmap>) {
    // This will recompose when bitmaps changes
}

If you’re replacing the entire list (like loading a new set of bitmaps), you can use mutableStateOf instead of mutableStateListOf. It would look like

var bitmaps by remember { mutableStateOf<List<Bitmap>>(emptyList()) }

LaunchedEffect(Unit) {
    val loadedBitmaps = getBitmapList(fileList)
    bitmaps = loadedBitmaps // Reassign the entire list
}

Many thanks to @Moe for the help, I finally got this working thanks to him and I want to leave a trace of what works for others because (to me) this was insanely difficult and I still don't fully understand everything about how it works.

I'm only going to show the specific code for remember/mutableStateListOf here i.e. where it goes in the main class and then composable and, for the moment, I'm not worrying about the blocking issue mentioned above - this is a simplest, probably poorly implemented, but working solution. Note that it's also not everything you need, all the compose layout is missing. Here is what's in the mainactivity class:

class MainActivity : ComponentActivity() {

    // get the folder to save images to
    val outputDirectory = getOutputDirectory()

    // read in a list of images in the images folder
    var fileList: ArrayList<File> = imageReaderNew(outputDirectory)

    override fun onCreate(savedInstanceState: Bundle?) {
        setContent {
            CameraApp1Theme {

                // create a mutablestatelistof and remember it for jetpack compose
                val bitmaps = remember { mutableStateListOf<Bitmap>() }

                // get a list of bitmaps of the images and add it to the bitmaps list
                val loadedBitmaps = getBitmapList(fileList)
                bitmaps.clear()
                bitmaps.addAll(loadedBitmaps)

                BottomSheetScaffold(
                    scaffoldState = scaffoldState,
                    sheetContent = {
                        PhotoBottomSheetContent(
                            // pass bitmaps to the composable
                            bitmaps = bitmaps,
                            modifier = Modifier.fillMaxWidth()
                        )
                    }
                )
                {
                   IconButton(
                        // triggered when the user open the photosheet
                        onClick = {
                            // read in a list of images in the images folder (update)
                            fileList = imageReaderNew(outputDirectory)

                            // get a list of bitmaps of the images and add it to the bitmaps list to update it
                            val loadedBitmaps = getBitmapList(fileList)
                            bitmaps.clear()
                            bitmaps.addAll(loadedBitmaps)
                        }
                    )
                    {
                    }
                }
            }
        }
    }


    // Get output directory for photos
    private fun getOutputDirectory(): File {

        //... get the directory here (internal or external etc.) ...

        // return absolute path to directory
        return fullpath
    }


    // Read in an arraylist of all saved images for this app
    private fun imageReaderNew(root: File): ArrayList<File> {

        //... build the list here ...

        // return filelist arraylist
        return fileList
    }

    private fun getBitmapList(fileList: ArrayList<File>): ArrayList<Bitmap> {

        // set up an empty bitmaps arraylist
        val bitmaps: ArrayList<Bitmap> = ArrayList()

        //... build the list here ...

        // return bitmaps arraylist
        return bitmaps
    }

}

Finally in the composable you will need to declare bitmaps like so:

@Composable
fun PhotoBottomSheetContent(
    //this is the basic working one
    bitmaps: List<Bitmap>
)
{
}
发布评论

评论列表(0)

  1. 暂无评论