[SOLVED] How to use mutableStateListOf in compose


This Question and Answer are collected from stackoverflow and tested by JTuto community, is licensed under
CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

Issue

Items get displayed as duplicates when I use remember with mutableStateListOf. so whats the right way of creating a mutable list that can hold a list of data classes in a composable.

sample code:

@Composable
fun WallpapersDetailScreen{
   val items  =   remember {
        mutableStateListOf<MultiFabItem>() 
    } 

 items.addAll( listOf(
     MultiFabItem(
         identifier = FabIdentifier.FAVOURITE.name,
         icon = ImageBitmap.imageResource(id = R.drawable.heart),
         label = "favourite"
     ),

     MultiFabItem(
         identifier = FabIdentifier.SET_AS_WALLPAPER.name,
         icon = ImageBitmap.imageResource(id = R.drawable.wallpaper),
           label = "Set As Wallpaper"
         )
   )
    }
     

Solution

You are adding item on each recomposition with

items.addAll( listOf(
     MultiFabItem(
         identifier = FabIdentifier.FAVOURITE.name,
         icon = ImageBitmap.imageResource(id = R.drawable.heart),
         label = "favourite"
     ),

     MultiFabItem(
         identifier = FabIdentifier.SET_AS_WALLPAPER.name,
         icon = ImageBitmap.imageResource(id = R.drawable.wallpaper),
           label = "Set As Wallpaper"
         )
   )

You can add your items inside remember only on composition and calling ImageBitmap.imageResource before adding to list. imageResource uses remember under the hood so you don’t have to worry for re-instantiation of images

   val heartBitmap = ImageBitmap.imageResource(id = R.drawable.heart)
   val wallpaperBitmap = ImageBitmap.imageResource(id = R.drawable.wallpaper)

   val items = remember {
        mutableStateListOf<MultiFabItem>().apply{
            addAll( listOf(
         MultiFabItem(
             identifier = FabIdentifier.FAVOURITE.name,
             icon = heartBitmap,
             label = "favourite"
         ),
    
         MultiFabItem(
             identifier = FabIdentifier.SET_AS_WALLPAPER.name,
             icon = wallpaperBitmap,
               label = "Set As Wallpaper"
             )
       )
        } 
    } 

Other option is simply checking if items is empty if so add items then.

if (items.isEmpty()) {
    items.addAll(
        listOf(
            MultiFabItem(
                identifier = FabIdentifier.FAVOURITE.name,
                icon = ImageBitmap.imageResource(id = R.drawable.heart),
                label = "favourite"
            ),

            MultiFabItem(
                identifier = FabIdentifier.SET_AS_WALLPAPER.name,
                icon = ImageBitmap.imageResource(id = R.drawable.wallpaper),
                label = "Set As Wallpaper"
            )
        )
    )
}

Answered By – Thracian

people found this article helpful. What about you?