orhanuckulac
orhanuckulac

Reputation: 45

Jetpack Compose Load URI Image on Screen

I am trying to pass a data class which has URI profileImage value on it and I want to populate UI with that profileImage uri value. when I try to "upload" from gallery and populate UI, it works as I wanted. But when I try to pass userDetails data class to my ProfileScreen composable, and get the profileImage value in a LaunchedEffect, it gives me the correct uri value, but for some reason Coil - AsyncImage is not populating the UI with that uri value.

1- I pass userDetail data class from HomeScreen to ProfileScreen

2- at the top of the composable code block, I do LaunchedEffect to update imageUri variable to hope that I populate the UI with userDetails?.profileImage?.toUri() value

3- when I try to upload an image by selecting from gallery, it works fine. I can populate UI like that.

All I want is to populate UI when user first enters the composable. LaunchedEffect is not working for some reason. And also, when I pick image from gallery, I get it's uri value. I tried copy pasting that uri to imageUri as "urivalue".toUri() it is not working too.

How can I solve this any ideas?

@Composable

 fun ProfileScreen(
     onSignOut: () -> Unit,
     viewModel: ProfileScreenViewModel = hiltViewModel(),
     userDetails: UserModel? ) {
     

var imageUri by remember { mutableStateOf<Uri?>(null) }

LaunchedEffect(true) {
    Log.i("MYTAG" , "IS EMPTY? ${userDetails?.profileImage?.toUri()}")
    imageUri = userDetails?.profileImage?.toUri()
}

val permissionLauncher = rememberLauncherForActivityResult(
    contract = ActivityResultContracts.PickVisualMedia(),
    onResult = {
        imageUri = it
        Log.i("MYTAG", "it $it")
    }
)


Column(
    modifier = Modifier.fillMaxSize(),
    verticalArrangement = Arrangement.Center,
    horizontalAlignment = Alignment.CenterHorizontally
) {
    AsyncImage(
        model = imageUri ?: R.drawable.ic_user_place_holder, // Use a default image resource
        contentDescription = "",
        modifier = Modifier
            .padding(4.dp)
            .size(150.dp)
            .clip(CircleShape),
        contentScale = ContentScale.Crop,
    )

    Spacer(modifier = Modifier.height(12.dp))

    Button(onClick = {
        permissionLauncher.launch(
            PickVisualMediaRequest(
                ActivityResultContracts.PickVisualMedia.ImageOnly
            )
        )
    }) {
        Text(text = "Pick Image")
    }
    Spacer(modifier = Modifier.height(16.dp))

    Button(onClick = onSignOut) {
        Text(text = "Sign out")
    }
}

}

Upvotes: 1

Views: 5167

Answers (1)

Megh Lath
Megh Lath

Reputation: 2138

Try using ImageBuilder instead of directly passing imageUri in model argument.

AsyncImage(
        model = ImageRequest.Builder(LocalContext.current)
            .data(imageUri)
            .placeholder(R.drawable.ic_user_place_holder)
            .build(),
       contentDescription = "",
        modifier = Modifier
            .padding(4.dp)
            .size(150.dp)
            .clip(CircleShape),
        contentScale = ContentScale.Crop,
    )

And if this doesn't work then imageUri might be null when image is build. In that case, you can trigger something to do force recompose in order to build image again.

Upvotes: 2

Related Questions