intel3
intel3

Reputation: 1

LazyColumn Recomposed when selected to pass url to AsyncImage

New to Jetpack compose, can someone explain why when i select an item in LazyRow and pass that url to the Image it will recomposed the whole row again? HOw should i be using the movieSelector variable?

@Composable
fun MovieHorizontalCarousel(viewModel: MovieViewModel = MovieViewModel()) {
    val movies: LazyPagingItems<Movie> = viewModel.movies.collectAsLazyPagingItems()

    Column(
        modifier = Modifier
            .fillMaxSize()
    ) {

        val movieSelector = remember { mutableStateOf("") }
        Carousel(
            movies = movies,
            onMovieSelected = { url -> movieSelector.value = url },
            Modifier
                .fillMaxWidth()
                .height(100.dp)
        )

        MoviePreview(
            movieSelector.value,
            modifier = Modifier
                .fillMaxWidth()
                .weight(1f)
        )
    }

}

@Composable
fun MoviePreview(url: String,
                 modifier: Modifier = Modifier) {
    AsyncImage(
        modifier = modifier
            .fillMaxSize()
            .background(Purple40),
        model = url,
        contentDescription = "Preview"
    )
}

@Composable
fun Carousel(movies: LazyPagingItems<Movie>,
             onMovieSelected: (String) -> Unit,
             modifier: Modifier = Modifier) {

    LazyRow(
        modifier = modifier
            .wrapContentSize()
            .background(Purple80),
        //horizontalArrangement = Arrangement.spacedBy(8.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        items (
            count = movies.itemCount,
            key = { index -> movies[index]?.id ?: index }
            //key = movies.itemKey{ item -> item.id }
        ) { index ->
            movies[index]?.let {
                MovieCarouselItem(movie = it,
                                  onMovieSelected = onMovieSelected)
            }
        }
    }
}

@Composable
fun MovieCarouselItem (movie: Movie,
                       onMovieSelected: (String) -> Unit,
                       modifier: Modifier = Modifier) {

    AsyncImage(
        modifier = modifier
            .size(81.dp)
            .clickable {
                onMovieSelected("https://image.tmdb.org/t/p/w500${movie.posterPath}")
            },
        model = "https://image.tmdb.org/t/p/w500${movie.posterPath}",
        contentDescription = "Movie Thumbnail" ,
        contentScale = ContentScale.Crop,
        placeholder = painterResource(id = R.drawable.photo)
    )
}

I am trying to display the image that the user selected from the lazyrow, it updated the image but also recomposed the list of movies.

Upvotes: 0

Views: 51

Answers (1)

Shadman Adman
Shadman Adman

Reputation: 431

Move the selection state outside the Column :

@Composable
fun MovieHorizontalCarousel(viewModel: MovieViewModel = MovieViewModel()) {
    val movies: LazyPagingItems<Movie> = viewModel.movies.collectAsLazyPagingItems()

    // Hoist state to avoid unnecessary recomposition of Carousel
    var selectedMovieUrl by remember { mutableStateOf("") }

    Column(
        modifier = Modifier
            .fillMaxSize()
    ) {
        Carousel(
            movies = movies,
            onMovieSelected = { url -> selectedMovieUrl = url },
            modifier = Modifier
                .fillMaxWidth()
                .height(100.dp)
        )

        MoviePreview(
            url = selectedMovieUrl,
            modifier = Modifier
                .fillMaxWidth()
                .weight(1f)
        )
    }
}

Upvotes: 0

Related Questions