/**/

我正在使用Kotlin开发一款Android应用程序.我需要在屏幕上显示云存储中的图片.现在,图片会显示,但它们会闪烁.我找不到用Kotlin 写的信息,我也不知道为什么会发生这种情况. 这是我目前的代码.

@Composable
fun UserInfo(navController: NavController, name: String, uid: String) {
    val storage = Firebase.storage
    val userRef = storage
        .reference
        .child("users/${uid}/photos")
        .child(name)
    var bitmap by remember { mutableStateOf<Bitmap?>(null) }
    val ONE_MEGABYTE: Long = 1024 * 1024
    userRef.getBytes(ONE_MEGABYTE).addOnSuccessListener {
        bitmap = BitmapFactory.decodeByteArray(it, 0, it.size)
    }
    ...

            if (userRef != null) {
                Image(
                    painter = rememberImagePainter(bitmap),
                    contentScale = ContentScale.FillBounds,
                    contentDescription = null,
                    modifier = Modifier
                        .width(100.dp)
                        .height(100.dp)
                        .clip(CircleShape)
                )
            ...

有人能帮帮我吗?谢谢.

我已经把代码移到了存储类,就像这样.

class Storage {
    val storage = Firebase.storage

    @Composable
    fun GetPhoto(uid: String, name: String): Bitmap? {
        val userRef = storage.reference
            .child("users/${uid}/photos")
            .child(name)
        var bitmap by remember { mutableStateOf<Bitmap?>(null) }
        val ONE_MEGABYTE: Long = 1024 * 1024
        userRef.getBytes(ONE_MEGABYTE).addOnSuccessListener {
            bitmap = BitmapFactory.decodeByteArray(it, 0, it.size)
        }
        return bitmap
        }
}

这是UserInfo View Now.

@Composable
fun UserInfo(navController: NavController, name: String, uid: String) {
...

 storage.GetPhoto(uid, name)
            val bitmap =
                Image(
                    painter = rememberImagePainter(storage.GetPhoto(uid, name)),
                    contentScale = ContentScale.FillBounds,
                    ...

这是我的UserInfo View的全部代码.

@Composable
fun UserInfo(navController: NavController, name: String, uid: String) {
val storage = Storage()
Column(
        modifier = Modifier
            .background(Beige)
            .fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .weight(1f),
        horizontalArrangement = Arrangement.Center
    )
    {          
            storage.GetPhoto(uid, name)         
            Image(
               painter = rememberImagePainter(storage.GetPhoto(uid, name)),
               contentScale = ContentScale.FillBounds,
               contentDescription = null,
               modifier = Modifier
                   .width(100.dp)
                   .height(100.dp)
                   .clip(CircleShape)
             )
        }
        Row(
             modifier = Modifier
                 .fillMaxWidth()
                 .weight(1f),
             horizontalArrangement = Arrangement.Center
        ) 
        {
             Button(modifier = Modifier.wrapContentWidth(),
                        colors = ButtonDefaults.textButtonColors(
                            backgroundColor = Pink,
                            contentColor = Brown,
                            disabledContentColor = Color.LightGray
                        ),
                        onClick = {
                        navController.navigate("PostHistory")
                        }
             ) {
                    Text(text = "Posts", fontSize = 20.sp)
               }
            }

推荐答案

问题在这里,似乎每次调用Firebase存储函数侦听器都会触发一些东西,使其侦听新的返回,这反过来又会每次更新您的bitmap状态,因为它是字节流,它设置的seems值总是与前一个值不同,在这种情况下,这足以让Compose触发re-composition.

userRef.getBytes(ONE_MEGABYTE).addOnSuccessListener {
     bitmap = BitmapFactory.decodeByteArray(it, 0, it.size)
}

我们可以做的是使用不会更改的key包装LaunchedEffect中的所有Firebase组件,防止它在后续的re-compositions上重新执行,在这种情况下,一旦您的bitmap状态从回调收到新值,这将触发组合更新UserInfo,LaunchedEffect将不会重新执行.

@Composable
fun UserInfo(navController: NavController, name: String, uid: String) {

    var bitmap by remember { mutableStateOf<Bitmap?>(null) }

    LaunchedEffect(Unit) {

        val storage = Firebase.storage
        val userRef = storage
            .reference
            .child("users/${uid}/photos")
            .child(name)

        val ONE_MEGABYTE: Long = 1024 * 1024

        userRef.getBytes(ONE_MEGABYTE).addOnSuccessListener {
            bitmap = BitmapFactory.decodeByteArray(it, 0, it.size)
        }
    }

    if (bitmap != null) {
        Image(
            painter = rememberImagePainter(bitmap),
            contentScale = ContentScale.FillBounds,
            contentDescription = null,
            modifier = Modifier
                .width(100.dp)
                .height(100.dp)
                .clip(CircleShape)
        )
    }
}

Android相关问答推荐

Material Design 网站的新设计已启动,但我找不到实现选项卡,该选项卡在哪里?

在 Android Studio 中保存数据

Android Studio:无法恢复密钥

具有自定义布局和 EditText 的 AlertDialog.Builder;无法访问视图

增强现实框架

如何在android中将毫秒转换为日期格式?

Activity 启动时如何显示 Snackbar?

Android ListView 标头

如何在android上的react native中启用实时重新加载?

EditText,清晰专注于touch 外

如何按应用过滤Android logcat?

如何在没有 Android 手机中烦人的对话框的情况下使用语音识别

使用 Google Guava 库进行 Android 开发是个好主意吗?

如何查看 Android APK 文件的内容?

如何将支持库中的操作栏添加到 PreferenceActivity?

反编译 APK 上的 .smali 文件

如何序列化对象并将其保存到 Android 中的文件中?

使用 proguard 时如何保留/排除特定的包路径?

CardView 在 Android L 中不显示阴影

如何禁用从/到 EditText 的复制/粘贴